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 Agent

You can also set a default agent for a specific flow. by using its default_agent parameter when decorating your flow function or creating the flow object.

import controlflow as cf

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

@cf.flow(default_agent=writer)
def research_flow():
    research_task = cf.Task("Research the topic", agents=[researcher])
    writing_task = cf.Task("Write a report") # will use the writer agent by default
    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. The agent specified by the flow (@flow(default_agent=...))
  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(default_agent=flow_agent)
def example_flow():
    task1 = cf.run("Task with flow default")
    task2 = cf.run("Task with specific agent", agents=[task_agent])
    
task3 = cf.run("Task with global default")


results = example_flow()

In this example:

  • task1 will use the flow_agent
  • task2 will use the task_agent
  • task3 will use the global_agent

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