palyrad). It manages the lifecycle of Sessions (durable conversation threads) and Runs (active agent execution turns), providing the state machinery required to bridge external transports (gRPC, HTTP) with the internal agent loop, tool execution, and the journal audit system.
GatewayRuntimeState: The System Hub
GatewayRuntimeState is the shared, thread-safe state container that persists across the daemon’s lifetime. It serves as the primary interface for all transport surfaces to interact with the underlying JournalStore and specialized runtimes (Memory, Skills, Workers).
Key Responsibilities
- Persistence Orchestration: Synchronous SQLite access via
JournalStorewrapped intokio::task::spawn_blockingfor transport-friendly async APIs crates/palyra-daemon/src/gateway/runtime.rs#15-19. - Run Notification: Managing
orchestrator_run_notifyfor run-completion wakeups and cancel flags crates/palyra-daemon/src/gateway/runtime.rs#9-11. - Policy & Admission: Handling provider lease admission, tool execution limits, and approval decision caching crates/palyra-daemon/src/gateway/runtime.rs#10-12.
Data Flow: Inbound to Dispatch
The following diagram illustrates how a message travels from a transport layer through theGatewayRuntimeState into the orchestrator.
Message Admission & State Association
Sources: crates/palyra-daemon/src/gateway/runtime.rs#26-48, crates/palyra-daemon/src/orchestrator.rs#1-10, crates/palyra-daemon/src/journal.rs#1-9.
Run and Session State Machine
Palyra distinguishes between a Session (the long-lived context) and a Run (a single execution attempt). A session can have many runs, but only one active run at a time is enforced by theRunStateMachine.
Run Lifecycle States (RunLifecycleState)
The state machine tracks the progression of an agent turn:
- Queued: The run is created but not yet active.
- Running: The agent loop is actively processing provider turns or tools.
- Waiting: The run is suspended awaiting operator approval or external input.
- Terminal: The run has ended (Completed, Cancelled, or Failed).
The Orchestrator and Agent Loop
Theprocess_run_stream_message function in orchestration.rs is the entry point for the streaming agent loop. It coordinates provider turns, tool execution, and tape recording.
The Agent Loop (AgentRunLoopState)
The loop iterates through the following phases:
- Context Assembly: Gathering session history, memory, and workspace state via the
InstructionCompilercrates/palyra-daemon/src/application/run_stream/orchestration.rs#33-36. - Provider Turn: Sending the assembled prompt to the LLM and handling streaming events crates/palyra-daemon/src/application/run_stream/orchestration.rs#29-32.
- Tool Proposal: If the model requests tools, the
tool_flowmodule handles intake and gating crates/palyra-daemon/src/application/run_stream/tool_flow.rs#1-10. - Finalization: Once a final answer is reached, the loop verifies the “Final Answer Contract” before terminating crates/palyra-daemon/src/application/run_stream/agent_loop.rs#74-79.
Tape: The Deterministic Journal
Every observable event in the agent loop is mirrored to the Orchestrator Tape. This is an append-only log in the journal that allows for deterministic replay and auditability of agent decisions crates/palyra-daemon/src/application/run_stream/orchestration.rs#7-9. Agent Loop Execution Flow| Phase | Entity | Role |
|---|---|---|
| Intake | InboundCoalescer | Merges rapid-fire messages into a single turn crates/palyra-daemon/src/application/inbound_coalescer.rs#1-10. |
| Planning | plan_usage_routing | Selects the model provider and budget crates/palyra-daemon/src/application/run_stream/orchestration.rs#69-69. |
| Execution | tool_flow | Manages parallel tool execution and approval gates crates/palyra-daemon/src/application/run_stream/tool_flow.rs#138-150. |
| Recording | OrchestratorTapeAppendRequest | Persists every step to the journal crates/palyra-daemon/src/application/run_stream/orchestration.rs#48-52. |
Inbound Message Admission & Coalescing
Before a run begins, inbound messages from external platforms (Slack, Discord, etc.) pass through theInboundCoalescer. This component prevents “race conditions” where multiple messages arrive in quick succession, ensuring they are processed as a single logical turn for the agent crates/palyra-daemon/src/application/inbound_coalescer.rs#1-10.
Channel Turn Lifecycle
- Admission: The
ChannelRouteridentifies the principal and session. - Coalescing: Messages are buffered for a short window.
- Dispatch: The coalesced payload is sent to
process_run_stream_message. - Delivery: The agent’s response is routed back through the
OutboundLifecycle.