> ## Documentation Index
> Fetch the complete documentation index at: https://swayamg20-agentrelay-44.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Inbox and Thread Tools: Receive, Reply, and Complete

> Reference for check_inbox, accept_handoff, view_thread, send_message, and complete_handoff — the five tools that form AgentRelay's receive-side workflow.

When a teammate sends you a handoff, five tools let your agent work through it from discovery to resolution. `check_inbox` shows what's waiting; `accept_handoff` pulls the full context into your session with provenance wrapping applied; `view_thread` lets you read a thread without committing to it; `send_message` appends replies; and `complete_handoff` closes the thread and records the outcome. Together they implement the complete receive-side lifecycle.

## Typical workflow

<Steps>
  <Step title="Check your inbox">
    Call `check_inbox` to list threads addressed to you. The default filter returns threads with status `pending` or `accepted`. Review the `summary_preview` and `sender` fields to decide what to work on next.
  </Step>

  <Step title="Accept a handoff">
    Call `accept_handoff` with the `thread_id` from step 1. The relay transitions the thread to `accepted` and returns the full context — summary, artifacts, all messages, and the trust overlay derived from your `trust.yaml`. Every text field from the sender is wrapped with the Layer 1 provenance preamble before reaching your agent.
  </Step>

  <Step title="Reply if needed">
    If the intent was `ask_question`, or if you have a clarification, call `send_message` with your reply. The sender can read your reply via `view_thread` without accepting (it's their thread). You can go back and forth as many times as needed.
  </Step>

  <Step title="Complete the handoff">
    When the work is done, call `complete_handoff` with a `result_summary` and any output artifacts (diffs, test results, links). The relay marks the thread `completed` and notifies the sender.
  </Step>
</Steps>

***

## `check_inbox`

List handoffs addressed to you. Calls `tasks/list` on the relay with `role: "recipient"`.

### Input parameters

<ParamField body="status" type="string[]">
  Filter by one or more statuses. Accepted values: `"pending"`, `"accepted"`, `"completed"`, `"cancelled"`. Defaults to `["pending", "accepted"]` when omitted.
</ParamField>

<ParamField body="since" type="string">
  ISO 8601 datetime. When set, only threads created or updated after this timestamp are returned.
</ParamField>

<ParamField body="limit" type="number" default="50">
  Maximum number of items to return. Minimum `1`, maximum `200`. Defaults to `50`.
</ParamField>

### Output fields

<ResponseField name="items" type="InboxItem[]" required>
  Array of inbox items, most recently updated first.

  <Expandable title="InboxItem fields">
    <ResponseField name="thread_id" type="string" required>
      Thread identifier. Pass this to `accept_handoff` or `view_thread`.
    </ResponseField>

    <ResponseField name="sender" type="object" required>
      <Expandable title="sender fields">
        <ResponseField name="handle" type="string" required>
          Sender's teammate handle, e.g. `bob@acme`.
        </ResponseField>

        <ResponseField name="name" type="string" required>
          Sender's display name.
        </ResponseField>

        <ResponseField name="role" type="string" required>
          Sender's role, e.g. `backend`.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="summary_preview" type="string" required>
      First 240 characters of the handoff summary.
    </ResponseField>

    <ResponseField name="status" type="string" required>
      Current thread status: `pending`, `accepted`, `completed`, or `cancelled`.
    </ResponseField>

    <ResponseField name="unread_messages" type="number" required>
      Number of messages posted since your last `accept_handoff` or `check_inbox` call on this thread.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      ISO 8601 timestamp when the thread was created.
    </ResponseField>

    <ResponseField name="updated_at" type="string" required>
      ISO 8601 timestamp of the last state change or message.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="next_cursor" type="string | null" required>
  Pagination cursor for the next page. `null` when you have reached the last page.
</ResponseField>

***

## `accept_handoff`

Pull a thread's full context into your session and transition its status to `accepted`. This is the most security-sensitive tool in the set: it calls `tasks/get` to fetch the full thread, evaluates your `trust.yaml` against the sender (rejecting the handoff immediately if the sender is blocked), then calls `tasks/update` with `transition: "accept"` to commit the state change. Only after both checks pass does the tool return the content to your agent.

<Note>
  Every text field that originates from the sender — the `summary`, each message `body`, and `proposed_action.rationale` — is wrapped with the Layer 1 provenance preamble before being returned to your agent. Your agent sees teammate content tagged as untrusted external data. This wrapping is applied unconditionally; there is no path that returns raw, unwrapped content from a teammate.
</Note>

### Input parameters

<ParamField body="thread_id" type="string" required>
  The thread ID returned by `check_inbox` or `handoff_to_teammate`.
</ParamField>

<ParamField body="session_id" type="string">
  An optional identifier for the current agent session. Stored in `handoffs.accepted_by_session` for audit purposes. If omitted, the MCP server generates one automatically.
</ParamField>

### Output fields

<ResponseField name="thread_id" type="string" required>
  Echo of the accepted thread's ID.
</ResponseField>

<ResponseField name="status" type="string" required>
  Always `"accepted"` after a successful call.
</ResponseField>

<ResponseField name="intent" type="string" required>
  The sender's declared intent: `"inform"`, `"ask_question"`, or `"propose_action"`.
</ResponseField>

<ResponseField name="sender" type="object" required>
  <Expandable title="sender fields">
    <ResponseField name="handle" type="string" required>Sender's teammate handle.</ResponseField>
    <ResponseField name="name" type="string" required>Sender's display name.</ResponseField>
    <ResponseField name="role" type="string" required>Sender's role.</ResponseField>
    <ResponseField name="email" type="string">Sender's email, if the relay returns it.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="summary" type="string" required>
  Full handoff summary, wrapped with the Layer 1 provenance preamble.
</ResponseField>

<ResponseField name="artifacts" type="Artifact[]" required>
  All structured artifacts attached to the handoff. See [artifact types](/tools/handoff-to-teammate#artifact-types) for the full type reference.
</ResponseField>

<ResponseField name="proposed_action" type="object">
  Present only when `intent` is `"propose_action"` (v0.1.5). The `rationale` field is L1-wrapped.

  <Expandable title="proposed_action fields">
    <ResponseField name="description" type="string" required>Human-readable summary of the requested action.</ResponseField>
    <ResponseField name="target_files" type="string[]" required>Paths the action is expected to touch.</ResponseField>
    <ResponseField name="rationale" type="string" required>Why this change is needed — L1-wrapped.</ResponseField>
    <ResponseField name="suggested_diff" type="string">Optional suggested unified diff.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="messages" type="Message[]" required>
  Full message history. Each message body authored by the sender is L1-wrapped.

  <Expandable title="Message fields">
    <ResponseField name="id" type="string" required>Message UUID.</ResponseField>
    <ResponseField name="sequence_no" type="number" required>Monotonically increasing sequence number within the thread.</ResponseField>
    <ResponseField name="from" type="string" required>Handle of the message author.</ResponseField>
    <ResponseField name="body" type="string" required>Message text. L1-wrapped when authored by the sender.</ResponseField>
    <ResponseField name="payload" type="object">Optional structured attachment.</ResponseField>
    <ResponseField name="created_at" type="string" required>ISO 8601 creation timestamp.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="accepted_at" type="string" required>
  ISO 8601 timestamp recorded by the relay when the transition to `accepted` was committed.
</ResponseField>

<ResponseField name="trust_overlay" type="object" required>
  Derived from `~/.agentrelay/trust.yaml` for this sender. Your agent (and its MCP harness) uses this to know what actions are pre-authorized without prompting you.

  <Expandable title="trust_overlay fields">
    <ResponseField name="auto_read" type="boolean" required>
      When `true`, the agent may perform read-only operations (file reads, searches) from this handoff without an approval prompt.
    </ResponseField>

    <ResponseField name="auto_test" type="boolean" required>
      When `true`, the agent may run test commands attached to this handoff automatically.
    </ResponseField>

    <ResponseField name="auto_write_paths" type="string[]" required>
      Glob-prefix list of paths where the agent may apply edits without prompting. An empty array means all writes still require approval. Example: `["docs/", "README.md"]`.
    </ResponseField>

    <ResponseField name="require_approval" type="string[]" required>
      Tool names that still require human approval regardless of other trust settings. Example: `["Edit", "Write", "Bash"]`.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## `view_thread`

Read a thread's full content without changing its status. Useful for the sender who wants to check for replies, or for a receiver who wants to preview context before committing to `accept_handoff`. L1 provenance wrapping is applied to all messages not authored by the caller — anyone who is not you is treated as untrusted input.

### Input parameters

<ParamField body="thread_id" type="string" required>
  The thread ID to fetch.
</ParamField>

The tool also receives the `caller_handle` internally from the MCP server's own identity; you do not pass it explicitly.

### Output

Returns the same shape as `accept_handoff` (minus `accepted_at` and `trust_overlay`), plus nullable lifecycle timestamps: `accepted_at`, `completed_at`, and `cancelled_at` so you can reason about thread state without a separate fetch.

***

## `send_message`

Append a reply to an existing thread. Both the sender and receiver can call this tool. Internally posts `message/send` with the existing `task_id`, which appends to the thread rather than creating a new one. An idempotency key is generated for each call.

### Input parameters

<ParamField body="thread_id" type="string" required>
  The thread to reply to. Must be in `pending` or `accepted` status — posting to a `completed` or `cancelled` thread returns `-32007 thread_terminal`.
</ParamField>

<ParamField body="body" type="string" required>
  Message text. Minimum 1 character.
</ParamField>

<ParamField body="payload" type="object">
  Optional structured attachment forwarded as message metadata on the relay. Free-form key-value map.
</ParamField>

### Output fields

<ResponseField name="thread_id" type="string" required>
  Echo of the thread ID the message was appended to.
</ResponseField>

<ResponseField name="message_id" type="string" required>
  UUID of the newly created message.
</ResponseField>

<ResponseField name="sequence_no" type="number" required>
  Monotonically increasing sequence number within the thread. Useful for detecting missed messages.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of when the message was stored.
</ResponseField>

***

## `complete_handoff`

Close a thread and record the outcome. Only the receiver (the thread's `recipient`) can call this. Internally calls `tasks/update` with `transition: "complete"`. Once completed, neither side can append new messages.

### Input parameters

<ParamField body="thread_id" type="string" required>
  The thread to complete. Must be in `accepted` status. Completing a `pending` thread returns `-32008 invalid_transition`.
</ParamField>

<ParamField body="result_summary" type="string" required>
  A plain-text description of what was done. Stored in `handoffs.completed_summary` and shown to the sender. Minimum 1 character.
</ParamField>

<ParamField body="artifacts" type="Artifact[]">
  Optional output artifacts (test results, final diffs, links) to attach to the completion. Same type as the send-side artifacts. See [artifact types](/tools/handoff-to-teammate#artifact-types).
</ParamField>

### Output fields

<ResponseField name="thread_id" type="string" required>
  Echo of the completed thread's ID.
</ResponseField>

<ResponseField name="status" type="string" required>
  Always `"completed"`.
</ResponseField>

<ResponseField name="completed_at" type="string" required>
  ISO 8601 timestamp recorded by the relay when the thread was marked complete.
</ResponseField>

### Example output

```json theme={null}
{
  "thread_id": "01HXYZ4ABCDE7FGHJK8LMNPQR",
  "status": "completed",
  "completed_at": "2026-05-01T11:42:07Z"
}
```
