Agent Lifecycle
How Daydreams agents process information and execute tasks.
Simple Overview
Think of an agent as following a simple loop:
- Something happens (input arrives)
- Agent thinks (uses LLM to decide what to do)
- Agent acts (performs actions or sends responses)
- Agent remembers (saves what happened)
- 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:
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).
- The target
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 newInputRef
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 temporaryWorkingMemory
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 theirrender
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
andoutputs
.
- The current persistent state of the active
- 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'shandler
function to run via theTaskRunner
. (See Actions and Tasks).
- For each identified
<output>
, the framework validates the content/attributes and runs the output'shandler
function to send the information externally (e.g., post a message). (See Outputs).
- For each identified
- Wait for Actions: The agent waits for any critical asynchronous actions
scheduled in this step to complete. Their results (
ActionResult
) are logged toWorkingMemory
. - 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 theMemoryStore
. - Return Results: The framework resolves the promise originally returned by
agent.send
oragent.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.