> ## Documentation Index
> Fetch the complete documentation index at: https://docs-code.palyra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Loop and Run Orchestration

<details>
  <summary>Relevant source files</summary>

  The following files were used as context for generating this wiki page:

  * apps/web/src/chat/chatSessionPresentation.ts
  * apps/web/src/console/sections/sessionCatalogPresentation.ts
  * crates/palyra-common/src/runtime\_contracts.rs
  * crates/palyra-common/src/tool\_catalog.rs
  * crates/palyra-daemon/src/application/approvals/mod.rs
  * crates/palyra-daemon/src/application/channel\_turn/mod.rs
  * crates/palyra-daemon/src/application/context\_compression.rs
  * crates/palyra-daemon/src/application/context\_engine.rs
  * crates/palyra-daemon/src/application/context\_references.rs
  * crates/palyra-daemon/src/application/delivery\_arbitration.rs
  * crates/palyra-daemon/src/application/execution\_gate.rs
  * crates/palyra-daemon/src/application/provider\_input.rs
  * crates/palyra-daemon/src/application/route\_message/orchestration.rs
  * crates/palyra-daemon/src/application/route\_message/tool\_flow\.rs
  * crates/palyra-daemon/src/application/run\_stream/agent\_loop.rs
  * crates/palyra-daemon/src/application/run\_stream/orchestration.rs
  * crates/palyra-daemon/src/application/run\_stream/tape.rs
  * crates/palyra-daemon/src/application/run\_stream/tool\_flow\.rs
  * crates/palyra-daemon/src/application/session\_compaction.rs
  * crates/palyra-daemon/src/application/session\_pruning.rs
  * crates/palyra-daemon/src/application/session\_queue.rs
  * crates/palyra-daemon/src/application/tool\_runtime/mod.rs
  * crates/palyra-daemon/src/application/tool\_security.rs
  * crates/palyra-daemon/src/auxiliary\_executor.rs
  * crates/palyra-daemon/src/background\_queue.rs
  * crates/palyra-daemon/src/execution\_backends.rs
  * crates/palyra-daemon/src/gateway.rs
  * crates/palyra-daemon/src/objective\_judge.rs
  * crates/palyra-daemon/src/tool\_posture.rs
  * crates/palyra-daemon/src/tool\_protocol.rs
  * crates/palyra-daemon/src/transport/grpc/services/gateway/service.rs
  * crates/palyra-daemon/src/transport/http/handlers/console/acp.rs
  * crates/palyra-daemon/src/transport/http/handlers/console/chat.rs
  * crates/palyra-daemon/tests/gateway\_grpc.rs
</details>

The Agent Loop is the iterative engine within the Palyra daemon that manages the lifecycle of a single "Run." It orchestrates the flow between the Model Provider (LLM), the Tool Runtime, and the Journal. The orchestration layer ensures that every step of an agent's reasoning and action is recorded to an append-only **Tape**, allowing for deterministic replay, auditability, and resumable execution.

## The Iterative Agent Loop

The loop is implemented primarily in `process_run_stream_message` [crates/palyra-daemon/src/application/run\_stream/orchestration.rs:3#15](http://crates/palyra-daemon/src/application/run_stream/orchestration.rs:3#15). It manages a state machine that transitions through resolving sessions, planning usage, building tool catalogs, and executing provider turns.

### Loop Components

* **AgentRunLoopState**: A pure, non-I/O struct that tracks the wall-clock budget and the growing message history [crates/palyra-daemon/src/application/run\_stream/agent\_loop.rs#3-8](http://crates/palyra-daemon/src/application/run_stream/agent_loop.rs#3-8). It enforces a default wall-clock budget of 15 minutes (`DEFAULT_AGENT_LOOP_WALL_CLOCK_BUDGET_MS`) [crates/palyra-daemon/src/application/run\_stream/agent\_loop.rs#25-25](http://crates/palyra-daemon/src/application/run_stream/agent_loop.rs#25-25).
* **RunProgressController**: A guardrail mechanism that detects repeated tool failures, denials, or "read loops" where the agent makes no progress [crates/palyra-daemon/src/application/run\_stream/agent\_loop.rs#150-154](http://crates/palyra-daemon/src/application/run_stream/agent_loop.rs#150-154).
* **Final Answer Contract**: A verification step that ensures the terminal answer produced by the model satisfies the run's objectives before completion [crates/palyra-daemon/src/application/run\_stream/agent\_loop.rs#45-46](http://crates/palyra-daemon/src/application/run_stream/agent_loop.rs#45-46).

### Run Execution Flow

The following diagram bridges the logical agent loop to the specific code entities in `palyra-daemon`.

**Agent Loop Orchestration Flow**

```mermaid theme={null}
graph TD
    subgraph "Natural Language Space"
        UserMsg["User Message / Trigger"]
        Loop["Iterative Reasoning Loop"]
        Result["Final Answer"]
    end

    subgraph "Code Entity Space (palyra-daemon)"
        PRSM["process_run_stream_message()"]
        ARLS["AgentRunLoopState"]
        RPC["RunProgressController"]
        Tape["OrchestratorTape (Journal)"]
        Provider["ModelProvider::request()"]
        ToolFlow["tool_flow::RunStreamPreparedToolExecution"]
    end

    UserMsg --> PRSM
    PRSM --> ARLS
    ARLS --> Loop
    Loop --> Provider
    Provider --> ToolFlow
    ToolFlow --> Tape
    ToolFlow --> Loop
    Loop --> RPC
    RPC -- "Loop Detection" --> Loop
    Loop --> Result
    Result --> PRSM
```

**Sources:** [crates/palyra-daemon/src/application/run\_stream/orchestration.rs#3-15](http://crates/palyra-daemon/src/application/run_stream/orchestration.rs#3-15), [crates/palyra-daemon/src/application/run\_stream/agent\_loop.rs#3-15](http://crates/palyra-daemon/src/application/run_stream/agent_loop.rs#3-15), [crates/palyra-daemon/src/application/run\_stream/tool\_flow.rs#1-10](http://crates/palyra-daemon/src/application/run_stream/tool_flow.rs#1-10)

## The Tape: Append-Only Run Journal

The **Tape** is the source of truth for a run's history. Every observable event—status updates, model tokens, tool proposals, approval requests, and tool results—is appended to the `OrchestratorTape` [crates/palyra-daemon/src/application/run\_stream/tape.rs#3-9](http://crates/palyra-daemon/src/application/run_stream/tape.rs#3-9).

### Tape Invariants

1. **Wire First**: The wire event is sent to the client before the tape append [crates/palyra-daemon/src/application/run\_stream/tape.rs#6-8](http://crates/palyra-daemon/src/application/run_stream/tape.rs#6-8).
2. **Sequential Integrity**: The `tape_seq` (sequence number) only advances after a successful journal append [crates/palyra-daemon/src/application/run\_stream/tape.rs#8-9](http://crates/palyra-daemon/src/application/run_stream/tape.rs#8-9).
3. **Redaction**: All text is passed through `redact_run_stream_text` to strip sensitive keys, URLs, and auth credentials before storage [crates/palyra-daemon/src/application/run\_stream/tape.rs#140-150](http://crates/palyra-daemon/src/application/run_stream/tape.rs#140-150).

**Sources:** [crates/palyra-daemon/src/application/run\_stream/tape.rs#1-10](http://crates/palyra-daemon/src/application/run_stream/tape.rs#1-10), [crates/palyra-daemon/src/application/run\_stream/tape.rs#79-108](http://crates/palyra-daemon/src/application/run_stream/tape.rs#79-108)

## Tool Proposal and Execution Flow

Tools move through a strict pipeline to ensure security and operator control.

1. **Proposal**: The agent proposes a tool call via the model response.
2. **Gate (Security & Approval)**: `evaluate_tool_proposal_security` checks the call against Cedar policies [crates/palyra-daemon/src/application/run\_stream/tool\_flow.rs#59-63](http://crates/palyra-daemon/src/application/run_stream/tool_flow.rs#59-63). If sensitive, it triggers a `PendingToolApproval` [crates/palyra-daemon/src/application/approvals/mod.rs#41-43](http://crates/palyra-daemon/src/application/approvals/mod.rs#41-43).
3. **Approval**: Interactive prompts are sent to the operator with a timeout (`TOOL_APPROVAL_RESPONSE_TIMEOUT`) [crates/palyra-daemon/src/gateway.rs#72-72](http://crates/palyra-daemon/src/gateway.rs#72-72).
4. **Execution**: If allowed, the tool is dispatched to the runtime via `execute_tool_with_runtime_dispatch` [crates/palyra-daemon/src/application/run\_stream/tool\_flow.rs#67-67](http://crates/palyra-daemon/src/application/run_stream/tool_flow.rs#67-67).
5. **Attestation**: Every outcome is signed with a `ToolAttestation` containing a SHA-256 hash of the inputs, outputs, and execution metadata [crates/palyra-daemon/src/tool\_protocol.rs#83-97](http://crates/palyra-daemon/src/tool_protocol.rs#83-97).

### Parallel Execution

Palyra supports bounded parallel execution (default max 4) for tools classified as `ReadOnlySafe`, `PathScoped`, or `IdempotentNetwork` [crates/palyra-daemon/src/application/run\_stream/tool\_flow.rs#93-150](http://crates/palyra-daemon/src/application/run_stream/tool_flow.rs#93-150).

**Tool Execution Pipeline**

```mermaid theme={null}
graph LR
    subgraph "Proposal Phase"
        Model["Model Turn"]
        Prop["NormalizedToolCall"]
    end

    subgraph "Gate Phase"
        Cedar["Cedar Policy Engine"]
        Appr["Approval Gate"]
    end

    subgraph "Execution Phase"
        Exec["Runtime Dispatch"]
        Attest["ToolAttestation (SHA-256)"]
    end

    Model --> Prop
    Prop --> Cedar
    Cedar --> Appr
    Appr -- "Authorized" --> Exec
    Exec --> Attest
    Attest -- "Append" --> Tape[("OrchestratorTape")]
```

**Sources:** [crates/palyra-daemon/src/application/run\_stream/tool\_flow.rs#1-10](http://crates/palyra-daemon/src/application/run_stream/tool_flow.rs#1-10), [crates/palyra-daemon/src/tool\_protocol.rs#1-15](http://crates/palyra-daemon/src/tool_protocol.rs#1-15), [crates/palyra-daemon/src/application/run\_stream/tool\_flow.rs#93-93](http://crates/palyra-daemon/src/application/run_stream/tool_flow.rs#93-93)

## Context Assembly and Budgeting

Before each model turn, Palyra assembles the context via `prepare_model_provider_input` [crates/palyra-daemon/src/application/provider\_input.rs#3-7](http://crates/palyra-daemon/src/application/provider_input.rs#3-7).

### Context Enrichment Layers

| Layer                  | Description                                                  | Source                  |
| :--------------------- | :----------------------------------------------------------- | :---------------------- |
| **Session Compaction** | Condenses old history into summaries to save tokens.         | `session_compaction.rs` |
| **Memory Recall**      | Hybrid retrieval (vector + FTS) of relevant facts.           | `recall.rs`             |
| **Trust Labels**       | Wraps recalled memory in fences to prevent prompt injection. | `memory.rs`             |
| **Pruning**            | Ephemeral removal of low-signal tokens for the current turn. | `session_pruning.rs`    |

### Session Compaction

To manage long-running sessions, the `ContextCompressor` identifies "protected" events (recent messages or pins) and condenses the rest into a `SessionCompactionPlan` [crates/palyra-daemon/src/application/session\_compaction.rs#3-17](http://crates/palyra-daemon/src/application/session_compaction.rs#3-17). This involves mining the history for durable facts and decisions, which are then persisted to the workspace [crates/palyra-daemon/src/application/session\_compaction.rs#134-155](http://crates/palyra-daemon/src/application/session_compaction.rs#134-155).

**Sources:** [crates/palyra-daemon/src/application/provider\_input.rs#1-13](http://crates/palyra-daemon/src/application/provider_input.rs#1-13), [crates/palyra-daemon/src/application/session\_compaction.rs#1-17](http://crates/palyra-daemon/src/application/session_compaction.rs#1-17)
