Daydreams Logo
Concepts

Agent Lifecycle

How Daydreams agents process information and execute tasks.

Simple Overview

Think of an agent as following a simple loop:

  1. Something happens (input arrives)
  2. Agent thinks (uses LLM to decide what to do)
  3. Agent acts (performs actions or sends responses)
  4. Agent remembers (saves what happened)
  5. Repeat

This loop continues as long as the agent is running, handling new inputs and responding intelligently based on its context and memory.

The Basic Flow

Here's what happens when your agent receives a Discord message:

Discord Message Arrives

Agent loads chat context & memory

Agent thinks: "What should I do?"

Agent decides: "I'll check the weather and respond"

Agent calls weather API (action)

Agent sends Discord reply (output)

Agent saves conversation to memory

Detailed Technical Explanation

The core of the Daydreams framework is the agent's execution lifecycle. This loop manages how an agent receives input, reasons with an LLM, performs actions, and handles results. Understanding this flow is crucial for building and debugging agents.

Let's trace the lifecycle of a typical request:

1. Input Reception

  • Source: An external system (like Discord, Telegram, CLI, or an API) sends information to the agent. This is usually configured via an extension.
  • Listener: An input definition within the agent or an extension listens for these events (e.g., a new message arrives).
  • Trigger: When the external event occurs, the input listener is triggered.
  • Invocation: The listener typically calls agent.send(...), providing:
    • The target context definition (which part of the agent should handle this?).
    • args to identify the specific context instance (e.g., which chat session?).
    • The input data itself (e.g., the message content).

2. agent.send - Starting the Process

  • Log Input: The framework logs the incoming information as an InputRef (a record of the input).
  • Initiate Run: It then calls the internal agent.run method to start or continue the processing cycle for the specified context instance, passing the new InputRef along.

3. agent.run - Managing the Execution Cycle

  • Load/Create Context: The framework finds the specific ContextState for the target instance (e.g., the state for chat session #123). If it's the first time interacting with this instance, it creates the state and its associated persistent memory (ContextState.memory). It also retrieves or creates the temporary WorkingMemory for this specific run.
  • Handle Concurrency: It checks if this context instance is already processing another request. If so, the new input is usually added to the ongoing run. If not, it sets up a new run.
  • Setup Run Environment: It prepares the environment for the LLM interaction, gathering all available actions, outputs, and relevant context information.
  • Start Step Loop: It begins the main processing loop, which iterates through one or more reasoning steps until the interaction is complete.

4. Inside the Step Loop - Perception, Reasoning, Action

Each iteration (step) within the agent.run loop represents one turn of the agent's core reasoning cycle:

  • Prepare State: The agent gathers the latest information, including:
    • The current persistent state of the active Context(s) (via their render functions).
    • The history of the current interaction from WorkingMemory (processed inputs, outputs, action results from previous steps).
    • Any new unprocessed information (like the initial InputRef or results from actions completed in the previous step).
    • The list of currently available actions and outputs.
  • Generate Prompt: This information is formatted into a structured prompt (using XML) for the LLM. The prompt clearly tells the LLM its instructions, what tools (actions/outputs) it has, the current state, and what new information needs attention. (See Prompting).
  • LLM Call: The agent sends the complete prompt to the configured LLM.
  • Process LLM Response Stream: As the LLM generates its response token by token:
    • The framework streams the response.
    • It parses the stream, looking for specific XML tags defined in the expected response structure (<reasoning>, <action_call>, <output>).
    • The LLM's thought process is extracted from <reasoning> tags and logged.
    • Instructions to perform actions (<action_call>) or send outputs (<output>) are identified.
  • Execute Actions & Outputs:
    • For each identified <action_call>, the framework validates the arguments against the action's schema and schedules the action's handler function to run via the TaskRunner. (See Actions and Tasks).
    • For each identified <output>, the framework validates the content/attributes and runs the output's handler function to send the information externally (e.g., post a message). (See Outputs).
  • Wait for Actions: The agent waits for any critical asynchronous actions scheduled in this step to complete. Their results (ActionResult) are logged to WorkingMemory.
  • Check Completion: The agent determines if the interaction is complete or if another reasoning step (another loop iteration) is needed based on defined conditions (shouldContinue hooks or remaining unprocessed logs).

5. Run Completion

  • Exit Loop: Once the loop condition determines no further steps are needed, the loop exits.
  • Final Tasks: Any final cleanup logic or onRun hooks defined in the context are executed.
  • Save State: The final persistent state (ContextState.memory) of all involved contexts is saved to the MemoryStore.
  • Return Results: The framework resolves the promise originally returned by agent.send or agent.run, providing the complete log (chain) of the interaction.

This detailed cycle illustrates how Daydreams agents iteratively perceive (inputs, results), reason (LLM prompt/response), and act (outputs, actions), using streaming and asynchronous task management to handle potentially complex interactions efficiently.

On this page