Skip to content

Commit

Permalink
Merge pull request #20 from jlowin/default-agents
Browse files Browse the repository at this point in the history
Add default agents to flows
  • Loading branch information
jlowin authored May 11, 2024
2 parents 62d5d4e + 215a5f5 commit 674e3b0
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 36 deletions.
4 changes: 3 additions & 1 deletion src/control_flow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from .settings import settings

# from .agent_old import ai_task, Agent, run_ai
from .core.flow import Flow
from .core.flow import Flow, reset_global_flow as _reset_global_flow
from .core.agent import Agent
from .core.task import Task
from .core.controller.controller import Controller
from .instructions import instructions
from .dx import ai_flow, run_ai, ai_task

_reset_global_flow()
5 changes: 1 addition & 4 deletions src/control_flow/core/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


class Agent(Assistant, ControlFlowModel, ExposeSyncMethodsMixin):
name: str = "Agent"
name: str
user_access: bool = Field(
False,
description="If True, the agent is given tools for interacting with a human user.",
Expand All @@ -42,6 +42,3 @@ async def run_async(self, tasks: list[Task] | Task | None = None):

def __hash__(self):
return id(self)


DEFAULT_AGENT = Agent(name="Marvin")
50 changes: 24 additions & 26 deletions src/control_flow/core/controller/instruction_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,18 @@ class TasksTemplate(Template):
You have been assigned to complete certain tasks. Each task has an
objective and criteria for success. Your job is to perform any required
actions and then mark each assigned task as successful. If a task also
actions and then mark each assigned task as successful. If a task
requires a result, you must provide it. Only work on tasks that are
assigned to you. If the task requires a result, do not also post the
result in a message, as this would be redundant. Messages should be used
only to provide context that is not captured in task results.
A "parent" is a task that spawned another task as a subtask. Generally,
the subtasks will need to be completed BEFORE the parent task. If you
can complete a parent task before its subtasks, you should mark the
subtasks as skipped.
Tasks have a "depends_on" list of upstream tasks that must be completed
before the task itself can be completed. The `mark_success` tool will
not be available until all dependencies are met.
assigned to you.
A task may have a "parent", meaning it is a subtask and should be
completed before its parent. You can `skip` a subtask if you are able to
complete the parent task first.
A task may have tasks it "depends_on", meaning it must be completed
after the tasks it depends on. Tasks will error if you try to complete
them before their dependencies are met.
### Current tasks
At the start of your turn, these are all the tasks being worked on. This
Expand All @@ -98,22 +95,23 @@ class TasksTemplate(Template):
result. For example, a task that asks you to choose, discuss, or perform
an action must be completed by posting messages before the task is
marked complete. The objective may require participation from multiple
agents. Do not mark a task as complete until the objective is fully met.
agents. Do not mark a task as complete until the objective is fully met.
If a task does take a result, do not also write the result in a message.
Some tasks may require collaboration with other agents to be completed; others
may take you multiple attempts. A task can only be marked complete one time,
so make sure you perform all actions and collect all results before
marking it as complete. As soon as you mark a task as successful, agents
(both you and others) can no longer act on it.
Some tasks may require collaboration with other agents to be completed;
others may take you multiple attempts. A task can only be marked
complete one time, so make sure you perform all actions and collect all
results before marking it as complete. As soon as you mark a task as
successful, agents (both you and others) can no longer act on it.
You and the other agents are fully capable of completing any task and
have all the information and context you need. Tasks should only be marked
failed due to technical errors like a broken or erroring tool or unresponsive human.
Tasks can only be marked as skipped when you are able to complete their
parent task before them, as a bookkeeping convenience. Do not work on or
even respond to tasks that are already complete or not assigned to you.
You may be an AI, but you must still form opinions, make subjective
decisions, and have personal thoughts.
have all the information and context you need. Tasks should only be
marked failed due to technical errors like a broken or erroring tool or
unresponsive human. Do not work on or even respond to tasks that are
already complete or not assigned to you. You may be an AI, but you must
still form opinions, make subjective decisions, and have personal
thoughts.
"""
tasks: list[Task]
Expand Down
22 changes: 20 additions & 2 deletions src/control_flow/core/flow.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from contextlib import contextmanager
from typing import Callable, Literal
from typing import TYPE_CHECKING, Callable, Literal

from marvin.beta.assistants import Thread
from openai.types.beta.threads import Message
Expand All @@ -10,14 +10,32 @@
from control_flow.utilities.logging import get_logger
from control_flow.utilities.types import AssistantTool, ControlFlowModel

if TYPE_CHECKING:
from control_flow.core.agent import Agent
logger = get_logger(__name__)


def default_agent():
from control_flow.core.agent import Agent

return [
Agent(
name="Marvin",
description="I am Marvin, the default agent for Control Flow.",
)
]


class Flow(ControlFlowModel):
thread: Thread = Field(None, validate_default=True)
tools: list[AssistantTool | Callable] = Field(
[], description="Tools that will be available to every agent in the flow"
)
agents: list["Agent"] = Field(
default_factory=default_agent,
description="The default agents for the flow. These agents will be used "
"for any task that does not specify agents.",
)
model: str | None = None
context: dict = {}

Expand Down Expand Up @@ -48,7 +66,7 @@ def __exit__(self, *exc_info):
return self.__cm.__exit__(*exc_info)


GLOBAL_FLOW = Flow()
GLOBAL_FLOW = None


def get_flow() -> Flow:
Expand Down
5 changes: 2 additions & 3 deletions src/control_flow/core/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
model_validator,
)

from control_flow.core.flow import get_flow
from control_flow.utilities.context import ctx
from control_flow.utilities.logging import get_logger
from control_flow.utilities.prefect import wrap_prefect_tool
Expand Down Expand Up @@ -86,9 +87,7 @@ def __repr__(self):
@field_validator("agents", mode="before")
def _default_agent(cls, v):
if v is None:
from control_flow.core.agent import DEFAULT_AGENT

return [DEFAULT_AGENT]
v = get_flow().agents
return v

@field_validator("result_type", mode="before")
Expand Down

0 comments on commit 674e3b0

Please sign in to comment.