Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.orxhestra.com/llms.txt

Use this file to discover all available pages before exploring further.

Every agent yields a stream of unified Event objects. All events share the same Event class and are distinguished by their type field using the EventType enum.

EventType values

EventTypeWhen emittedDescription
USER_MESSAGEUser input persisted by RunnerThe user’s message at the start of a turn
AGENT_MESSAGEAgent responseFinal answers, thoughts, tool call requests, or partial streaming chunks
TOOL_RESPONSETool execution resultThe result returned by a tool after execution
AGENT_STARTStart of astream()Marks the beginning of an agent’s execution
AGENT_ENDEnd of astream()Marks the end of an agent’s execution

Convenience properties

PropertyTypeDescription
event.textstrConcatenated text from all text parts in the event’s content
event.thinkingstrConcatenated thinking parts (extended thinking models like Claude with thinking enabled)
event.datadict | NoneFirst data part’s dict, or None
event.tool_namestr | NoneName of the tool (for TOOL_RESPONSE events or first tool call)
event.tool_inputdict | NoneInput arguments passed to the first tool call
event.tool_callslist[ToolCallPart]List of ToolCallPart objects from the LLM response (access .tool_name, .args, .tool_call_id)
event.has_tool_callsboolTrue if the event contains tool call requests
event.errorstr | NoneError message from tool response or metadata

Key methods

MethodDescription
event.is_final_response()Returns True if this is the agent’s final answer (an AGENT_MESSAGE with no tool calls and not a partial streaming chunk)
event.to_langchain_message()Converts the event to the corresponding LangChain message type (HumanMessage, AIMessage, ToolMessage, etc.)
Event.from_langchain_message(msg)Class method that creates an Event from a LangChain message
Event.new_id()Static method that generates a new unique event ID (UUID)

Checking event types

Use the EventType enum and convenience methods instead of isinstance checks:
from orxhestra.events.event import Event, EventType

# Check for final response (replaces isinstance(event, FinalAnswerEvent))
if event.is_final_response():
    print(event.text)

# Check for tool calls (replaces isinstance(event, ToolCallEvent))
if event.has_tool_calls:
    for tc in event.tool_calls:
        print(f"Calling {tc.tool_name} with {tc.args}")

# Check for tool results (replaces isinstance(event, ToolResultEvent))
if event.type == EventType.TOOL_RESPONSE:
    print(f"{event.tool_name} returned: {event.text}")

# Check for agent lifecycle
if event.type == EventType.AGENT_START:
    print(f"Agent {event.agent_name} starting")

Metadata conventions

Events use the metadata dict for additional context. Common keys:
KeyDescription
react_stepThe ReAct loop iteration number
errorError message string when something went wrong
exception_typeThe Python exception class name (e.g. "ValueError")
scratchpadInternal reasoning or planning notes from the agent

EventActions

Events carry EventActions for side-effects:
class EventActions(BaseModel):
    state_delta: dict[str, Any] = {}       # merged into session state
    artifact_delta: dict[str, int] = {}    # artifact filenames → version saved
    transfer_to_agent: str | None = None   # trigger agent handoff
    escalate: bool | None = None           # stop parent LoopAgent
    skip_summarization: bool | None = None
    end_of_agent: bool | None = None
    compaction: EventCompaction | None = None

Event Filters

The orxhestra.events.filters module provides reusable functions for preparing session events before they are sent to the LLM. These are used internally by LlmAgent and available for custom agents.

should_include_event(event)

Returns True if the event should be included in LLM context. Filters out:
  • Partial (streaming) events
  • Lifecycle events (AGENT_START, AGENT_END)
  • Error-only metadata events
  • Scratchpad notes
  • Empty AGENT_MESSAGE events (no text, data, or tool calls)
from orxhestra.events.filters import should_include_event

visible = [e for e in session.events if should_include_event(e)]

apply_compaction(events)

Replaces raw events with compaction summaries where applicable. When events carry an EventActions.compaction entry, all raw events within that timestamp range are replaced by a single synthetic event containing the summary.
from orxhestra.events.filters import apply_compaction

events = apply_compaction(session.events)
# Compacted ranges become single summary events
Both functions are also re-exported from orxhestra.events:
from orxhestra.events import should_include_event, apply_compaction

LlmResponse

AGENT_MESSAGE events may carry an llm_response: LlmResponse field with token usage and model version:
event.llm_response.input_tokens
event.llm_response.output_tokens
event.llm_response.model_version

Signed Events

Agents with a signing_key automatically sign every event they emit using Ed25519. This provides cryptographic proof of which agent produced each event.
Property / MethodTypeDescription
event.signaturestr | NoneBase64url-encoded Ed25519 signature
event.signer_didstrdid:key identifier of the signing agent
event.is_signedboolTrue if the event carries a signature
event.verify_signature()boolVerify the signature using the signer’s DID public key
event.signable_payload()dictCanonical dict of fields included in the signature (id, type, timestamp, agent_name, branch, content_text)
# Verify a signed event
if event.is_signed:
    valid = event.verify_signature()
    print(f"Signed by {event.signer_did}: {'valid' if valid else 'invalid'}")
Requires orxhestra[auth] (pip install orxhestra[auth]).