ControlFlow

repository·main·Indexed 23 days ago

https://github.com/prefect-archive/controlflow

A Python framework for building structured, observable, and predictable agentic AI workflows. ControlFlow decomposes complex processes into Tasks (discrete units of work), Agents (specialized AI entities with specific tools and models), and Flows (orchestrations that combine tasks into multi-step behaviors). It supports structured outputs via Pydantic, human-in-the-loop interaction, and multi-agent collaboration through shared context and message passing.

Tokens
64.1K
Snippets
158
Records
238
Agent score
80%

What's inside controlflow

  1. What is a Flow in ControlFlow?

    main

    A Flow is a high-level container used to encapsulate and orchestrate entire AI-powered workflows. It serves as the primary orchestration mechanism for managing the lifecycle of a complex application.

    Key responsibilities of a Flow include:

    • Orchestration: Managing the execution of discrete tasks and defining the dependencies and relationships between them.
    • State Management: Maintaining a consistent shared context across all components (agents, tools, and tasks) to allow for effective communication and collaboration.
    • Resource Management: Providing a structured environment for assigning agents to specific tasks and managing data flow.
    • Abstraction: Allowing developers to focus on application logic while the framework handles agent selection and error handling.
  2. What is an Agent in ControlFlow?

    main

    In ControlFlow, an Agent is an autonomous entity responsible for executing specific tasks within a workflow. Agents use Large Language Models (LLMs) to perform functions like text generation, question answering, and user interaction.

    Key characteristics of Agents include:

    • Tailored Capabilities: Each agent can be configured with unique instructions, specific tools, and specific models to suit a particular role or domain.
    • Autonomy: Agents operate independently to achieve objectives based on the provided context and instructions.
    • Interaction: Agents can interact with other agents or with human users to complete complex workflows.
    • Task Assignment: Developers optimize workflows by assigning the most suitable agent to each specific task within the control flow.
  3. What is the Agentic Loop in ControlFlow?

    main

    The agentic loop is the iterative process of invoking AI agents to make progress towards a goal. It consists of four conceptual steps:

    1. Prompt: Gathering and compiling relevant information into an LLM prompt.
    2. Invoke: Passing the prompt to an AI agent to generate a response.
    3. Evaluate: Determining if the agent wants to use a tool, post a message, or take another action.
    4. Repeat: Using the evaluation result to generate a new prompt and starting again.

    ControlFlow provides the abstractions necessary to manage this loop using standard software development paradigms, preventing agents from getting 'stuck' or running indefinitely.

  4. What is a Task in ControlFlow

    main

    A Task is the fundamental building block of a ControlFlow workflow. It represents a discrete objective or goal that an AI agent is assigned to solve.

    Key characteristics of a Task include:

    • Objective & Instructions: Defines what the task is and how the agent should approach it.
    • Expected Result Type: Specifies the format or type of data the task should produce.
    • Context & Tools: Provides the necessary information or capabilities required to complete the objective.
    • Agents: Tasks are executed by one or more agents assigned to them, allowing developers to match specific tasks with agents that have the appropriate specialized capabilities or model characteristics.
    • Dependencies: Tasks can have dependencies to define execution order, ensuring that a task's output is available as input for subsequent tasks or that prerequisites are met before execution.
  5. What is flow engineering?

    main

    Flow engineering is an approach to designing and optimizing agentic workflows for Large Language Models (LLMs). Unlike prompt engineering, which focuses on the natural-language content of individual messages, flow engineering focuses on the structural design of the workflow itself.

    Key objectives of flow engineering include:

    • Guiding decision-making: Using the workflow structure to direct the agent's process.
    • Improving output quality: Designing steps, decision points, and feedback loops to ensure better results.
    • Task decomposition: Breaking complex tasks into smaller, manageable components.
    • Sequence optimization: Defining the optimal order of actions for an agent to follow.
    • Control and domain expertise: Incorporating domain-specific knowledge and best practices into the structured sequence of actions to improve agent effectiveness, efficiency, and adaptability.
  6. Assign tools at different levels in ControlFlow

    main

    In ControlFlow, you can assign tools at three distinct levels to control agent capabilities and security. This hierarchical assignment allows you to restrict specific capabilities to specific parts of your workflow:

    1. Flow Level: Tools assigned to the @cf.flow decorator are available to any agent participating in that flow. Use this for global utilities like logging or user notifications.
    2. Agent Level: Tools assigned to a cf.Agent instance are available to that specific agent throughout the workflow.
    3. Task Level: Tools passed to cf.run() (or a cf.Task definition) are only available while that specific task is executing. Use this for sensitive or specialized operations like reading specific files.

    Tools can be any Python function. For best results, ensure they have clear type annotations and descriptive docstrings, as agents use these to understand how and when to call them.

    import controlflow as cf
    
    # 1. Agent-level tool
    agent = cf.Agent(name="FileSearcher", tools=[list_files])
    
    # 2. Flow-level tool
    @cf.flow(tools=[update_user], default_agent=agent)  
    def file_search_flow(query: str, directory: str):
        
        # 3. Task-level tool
        cf.run(
            "Analyze the contents...",
            tools=[read_file],
            depends_on=[found_files]
        )
  7. Constrain task outputs with result_type

    main

    The result_type parameter in cf.run allows you to constrain the output of a task to a specific set of values. When provided with a list of strings, the agent will attempt to map its reasoning to one of those specific options, ensuring predictable and structured outputs for classification or selection tasks.

    result_type=["Politics", "Technology", "Sports", "Entertainment", "Science"]
  8. How ControlFlow works: Tasks, Agents, and Flows

    main

    ControlFlow is built on three core abstractions that allow you to build agentic AI workflows:

    • Tasks: Discrete, observable units of work that an AI performs.
    • Agents: Specialized AI entities assigned to tasks to provide specific expertise or behaviors.
    • Flows: Orchestrations that combine multiple tasks into complex, multi-step behaviors. A flow acts as a shared context for a series of tasks.

    You can mix standard Python functions with agentic tasks within a flow, allowing for incremental complexity.

  9. Compose tasks into a workflow using @cf.flow

    main

    A flow provides shared context and history for multiple agents across multiple tasks. You can create a flow by applying the @cf.flow decorator to a Python function. Inside a flow, you can use standard Python logic (like if/else statements) to dynamically adjust the workflow based on the results returned by cf.run() calls.

    import controlflow as cf
    
    # Create agents
    classifier = cf.Agent(
        name="Email Classifier",
        model="openai/gpt-4o-mini",
        instructions="You are an expert at quickly classifying emails. Always "
                     "respond with exactly one word: either 'important' or 'spam'."
    )
    
    responder = cf.Agent(
        name="Email Responder",
        model="openai/gpt-4o",
        instructions="You are an expert at crafting professional email responses. "
                     "Your replies should be concise but friendly."
    )
    
    # Create the flow
    @cf.flow
    def process_email(email_content: str):
    
        # Classify the email
        category = cf.run(
            f"Classify this email",
            result_type=["important", "spam"],
            agents=[classifier],
            context=dict(email=email_content),
        )
    
        # If the email is important, write a response
        if category == "important":
            response = cf.run(
                f"Write a response to this important email",
                result_type=str,
                agents=[responder],
                context=dict(email=email_content),
            )
            return response
    
        # Otherwise, no response is needed for spam email
        else:
            print("No response needed for spam email.")
    
    # Run the flow on each email
    for email in emails:
        response = process_email(email)
        print(response)
  10. Specify task results with `result_type`

    main

    ControlFlow tasks use the result_type parameter to translate unstructured AI responses into structured, programmatic data. By default, the result_type is a str. Specifying a type ensures the output conforms to a schema that can be reliably used by downstream tasks.

    Common primitive types include:

    • int or float for numeric results.
    • bool for true/false values.
    • list[T] or dict[K, V] for collections.
    • None when no result is expected (e.g., for side-effect only tasks).
  11. What are Tools in ControlFlow

    main

    Tools are specialized functions or resources that agents use to perform tasks that go beyond natural language processing. They allow agents to interact with the external world or perform specialized computations.

    Common examples of tools include:

    • Python functions
    • API integrations
    • Libraries
    • Database access functions
    • Data processing and analysis routines
    • External service interactions
    • Mathematical calculation functions

    Tools are defined and associated with tasks or agents to create modular and extensible AI-powered workflows.

  12. When to use Tasks vs. Agents in ControlFlow

    main

    In ControlFlow, you should follow an incremental approach to building workflows:

    1. Start with Tasks

    Always begin by defining your workflow using cf.Task. Tasks are the primary way to:

    • Define your workflow: Create a roadmap of steps.
    • Set clear objectives: Each task has a specific goal and an expected result_type.
    • Maintain control: Tasks provide fine-grained control over the application logic.

    Note: If you create a cf.Task without providing an agents list, ControlFlow automatically assigns a default agent.

    2. Add Agents to Steer Behavior

    Introduce cf.Agent instances when you need to fine-tune how tasks are performed. Use agents for:

    • Specialized Expertise: When a task requires specific knowledge or skills.
    • Consistent Personality: To maintain a specific tone or approach.
    • Access to Specific Tools: When tasks require specialized functions or APIs.