Outputs
How Daydreams agents send information and responses.
Outputs are how Daydreams agents communicate results or send information to external systems or users. If Inputs are how agents "listen," Outputs are how they "speak" or "act" based on the LLM's reasoning.
Examples of outputs include:
- Sending a message to a Discord channel or Telegram chat.
- Posting a tweet.
- Returning a response in a CLI session.
- Calling an external API based on the agent's decision (though Actions are often better for this if a response is needed).
Defining an Output
Outputs are defined using the output
helper function exported from
@daydreamsai/core
. Each definition specifies how the agent should structure
information for a particular output channel and how to execute the sending
logic.
Key Parameters:
type
(string): Unique identifier used in<output type="...">
.description
/instructions
(string, optional): Help the LLM understand what the output does and when to use it.schema
(Zod Schema, optional): Defines the structure and validates the content placed inside the<output>
tag by the LLM. Defaults toz.string()
.attributes
(Zod Schema, optional): Defines and validates attributes placed on the<output>
tag itself (e.g.,<output type="discord:message" channelId="...">
). These provide necessary parameters for thehandler
.handler
(Function): Executes the logic to send the information externally. It receives:data
: The validated content from theschema
.ctx
: The context state (ContextState
) augmented with the specificoutputRef
for this call (OutputRef
). Attributes parsed from the tag are found inctx.outputRef.params
.agent
: The agent instance.- It can optionally return an
OutputRefResponse
(or array thereof) to update the log entry or mark it as processed.
format
(Function, optional): Customizes the log representation of theOutputRef
.examples
(string[], optional): Provides concrete examples to the LLM on how to structure the<output>
tag.install
/enabled
/context
(Functions/Context, optional): Similar to Actions and Inputs for setup, conditional availability, and context scoping.
LLM Interaction
- Availability: Enabled outputs are presented to the LLM within the
<available-outputs>
tag in the prompt, including their type, description, instructions, content schema (content_schema
), attribute schema (attributes_schema
), and examples. - Invocation: The LLM generates an output by including an
<output>
tag in its response stream, matching one of the available types. It must provide any required attributes defined in theattributes
schema and the content inside the tag matching theschema
.
Execution Flow
- Parsing: When the framework parses an
<output>
tag from the LLM stream (handleStream
instreaming.ts
), it extracts thetype
,attributes
, andcontent
. - Log Creation: An initial
OutputRef
log is created (getOrCreateRef
instreaming.ts
). - Processing: Once the tag is fully parsed (
el.done
), the engine callshandleOutput
(handlers.ts
). - Validation:
handleOutput
finds the corresponding output definition bytype
. It validates the extractedcontent
against theoutput.schema
and the extractedattributes
against theoutput.attributes
schema. - Handler Execution: If validation passes,
handleOutput
executes theoutput.handler
function, passing the validated content (data
) and the context state augmented with theoutputRef
(ctx
). Attributes are accessed viactx.outputRef.params
. - External Action: The
handler
performs the necessary external operation (e.g., sending the Discord message). - Logging: The
handler
can optionally return data to update theOutputRef
log. TheOutputRef
is added to theWorkingMemory
.
Outputs vs. Actions
While outputs and actions share similar structures, they serve different purposes:
Feature | Actions | Outputs |
---|---|---|
Primary purpose | Two-way interaction (call -> result -> LLM) | One-way communication (LLM -> external) |
Return value | Result is crucial for next LLM step | Result usually not directly needed by LLM |
State mutation | Commonly used to update context state | Can update state but less common |
Usage pattern | LLM requests data or triggers process | LLM communicates final response or notification |
Error handling | Errors often returned to LLM for reaction | Errors handled internally (logged/retried) |
When to Use Outputs vs. Actions
- Use outputs when: The primary goal is to communicate outward (send a message, display UI, log data), and you don't need the result of that communication for the LLM's immediate next reasoning step.
- Use actions when: You need the result of the operation (e.g., data fetched from an API, status of a transaction) for the LLM to continue its reasoning process or make subsequent decisions.
Best Practices for Outputs
- Keep outputs focused: Each output definition should have a single, clear
responsibility (e.g.,
discord:message
,log:event
). - Handle errors gracefully: The
handler
should containtry...catch
blocks for external calls and report failures appropriately (e.g., log an error, perhaps emit anerror
event) without crashing the agent. - Consider asynchronous processing: For outputs involving potentially slow
external systems, ensure the
handler
isasync
and handles the operation without blocking the main agent loop excessively. - Track important outputs in context: If the fact that an output occurred
is important for future agent decisions (e.g., remembering a message was
sent), update the relevant context memory within the
handler
. - Use descriptive names and schemas: Clearly define the
type
,schema
, andattributes
so the LLM understands exactly how to use the output. Provide goodexamples
.
Outputs allow the agent to respond and communicate, completing the interaction loop initiated by Inputs and guided by Actions.