ControlFlow uses a default agent when no specific agents are assigned to a task. Understanding how to configure and override this default agent at different levels can help you create more flexible and customized workflows.

Changing the Global Default Agent

The global default agent (whose name, of course, is Marvin) uses whatever default model you’ve configured. It has a basic set of general-purpose instructions and is not equipped with any tools.

To change the global default agent, assign a new agent to controlflow.defaults.agent:

import controlflow as cf

# Create a new agent
agent = cf.Agent('Deep Thought', instructions='Answer every question with 42')

# Set the global default agent
cf.defaults.agent = agent

# Create a task without specifying an agent
task = cf.Task('What is 2 + 2?')
task.run()  # Result: 42

Changing a Flow’s Default Agents

You can also set a default agent (or agents) for a specific flow. This allows you to use different default agents for different parts of your application without changing the global default.

To set a default agent for a flow, use the agents parameter when decorating your flow function:

import controlflow as cf

researcher = cf.Agent('Researcher', instructions='Conduct thorough research')
writer = cf.Agent('Writer', instructions='Write clear, concise content')

@cf.flow(agents=[researcher, writer])
def research_flow():
    research_task = cf.Task("Research the topic")
    writing_task = cf.Task("Write a report")
    return writing_task

result = research_flow()

In this example, both the research_task and writing_task will use the researcher and writer agents by default.

Agent Selection Precedence

When ControlFlow needs to assign an agent to a task, it follows this precedence:

  1. Agents specified directly on the task (task.agents)
  2. Agents specified for the flow (@flow(agents=[...]))
  3. The global default agent (controlflow.defaults.agent)

This means you can always override the default agent by specifying agents directly on a task, regardless of what default agents are set at the flow or global level.

import controlflow as cf

global_agent = cf.Agent('Global', instructions='I am the global default')
cf.defaults.agent = global_agent

flow_agent = cf.Agent('Flow', instructions='I am the flow default')

task_agent = cf.Agent('Task', instructions='I am specified for this task')

@cf.flow(agents=[flow_agent])
def example_flow():
    task1 = cf.Task("Task with flow default")
    task2 = cf.Task("Task with specific agent", agents=[task_agent])
    return task1, task2

results = example_flow()

In this example:

  • task1 will use the flow_agent
  • task2 will use the task_agent
  • If we created a task outside of example_flow, it would use the global_agent

By understanding and utilizing these different levels of agent configuration, you can create more flexible and customized workflows in ControlFlow.