Contexts
Managing state, memory, and behavior for agent interactions.
In Daydreams, a Context defines a specific scope or environment for your agent's interactions or tasks. Think of it as a dedicated workspace that holds the state, memory, available tools (actions, inputs, outputs), and specific instructions relevant to that particular job.
You might use different contexts for:
- Handling individual user chat sessions (
chatContext
). - Managing a specific game state (
gameContext
). - Executing a complex workflow or process (
workflowContext
). - Interacting with a specific external system (
externalApiContext
).
Each running instance of a context (e.g., the chat session with user A) maintains its own unique state and memory, separate from other instances (like the chat session with user B).
Defining a Context
You define context types using the context
function from @daydreamsai/core
.
Key Definition Parameters:
-
type
: Unique string identifying the context type. -
schema
: Zod schema for arguments needed to identify a context instance. Use.describe()
on fields for clarity. -
key
: (Optional) Function(args) => string
to create a unique instance key from arguments. -
create
: (Optional) Function(state, agent) => TMemory
defining the initial structure of the instance's persistent memory (ctx.memory
). -
render
: (Optional) Function(state) => string | XMLElement | ...
formatting the currentstate.memory
for the LLM prompt. Keep it concise and relevant. -
instructions
/description
: (Optional) Provide guidance to the LLM about the context. -
Lifecycle Hooks (
onStep
,onRun
, etc.): (Optional) Add custom logic at different points in the execution cycle. -
Configuration (
model
,maxSteps
, etc.): (Optional) Override agent defaults for this context type.
Context Memory (ctx.memory
)
The most important concept for managing state within a context is its persistent memory.
- Definition: The structure and initial values are defined by the
create
function in yourcontext
definition. - Access: Within context lifecycle hooks (like
onStep
) and within thehandler
of any action, input, or output associated with this context, you can access the current instance's memory viactx.memory
. - Persistence: Changes made to
ctx.memory
during an agent run are automatically saved by the framework to the configuredMemoryStore
at the end of the run cycle. - Loading: When an agent run starts for a specific context instance, the
framework loads its saved memory from the
MemoryStore
intoctx.memory
.
Associating Components (Actions/Inputs/Outputs)
While you can define components globally, it's often better to associate them
directly with the context they belong to using the chained .setActions()
,
.setInputs()
, and .setOutputs()
methods. This provides better organization
and ensures components have typed access to the correct context memory.
You can also define them inline using the actions
, inputs
, or outputs
properties directly within the context({...})
definition, though the chained
methods often offer superior type inference.
Working with Context Instances
You typically interact with specific context instances through the agent
object:
-
agent.getContext({ context: chatContext, args: { sessionId: "xyz", userId: "user1" } })
: Retrieves theContextState
for the specified instance. If it doesn't exist, it creates it (runningcreate
if needed) and loads its memory. -
agent.run({ context: chatContext, args: { sessionId: "xyz", userId: "user1" }, ... })
: Starts (or continues) the agent's processing loop specifically for this context instance. -
agent.getContextById("chat:session-xyz")
: (Less common) Retrieves a context instance directly by its full ID if you know it. -
agent.saveContext(contextState)
: Manually saves the state. Usually handled automatically by the agent lifecycle.
Context Memory vs. Working Memory
It's important not to confuse the persistent Context Memory (ctx.memory
)
with the temporary Working Memory.
- Context Memory (
ctx.memory
): Specific to a context instance. Holds the persistent state (like chat history). Defined bycreate
. Saved/loaded by theMemoryStore
. Used byrender
. - Working Memory: Exists only for the duration of a single
agent.run
. Holds the temporary log of inputs, outputs, thoughts, and action calls/results for that specific run. Used to build the prompt at each step.
Best Practices
- Scope Appropriately: Design contexts around distinct tasks or interaction boundaries.
- Define Memory Clearly: Use interfaces (like
ChatMemory
) for your context memory structure. Initialize it properly increate
. - Keep
render
Concise: Only include state inrender
that is essential for the LLM's immediate reasoning. Avoid overly large state dumps. - Use Zod Schemas: Clearly define
schema
for context arguments with.describe()
. - Associate Components: Link actions, inputs, and outputs to their relevant contexts for better organization and type safety.
Contexts provide the structure for organizing your agent's knowledge, state, and capabilities, enabling complex and stateful interactions.