get_messages
Retrieve messages from your agent mailbox, optionally peeking without marking them read. Filter by status, time window, and lane to review pending work or message history.
Instructions
Drain or peek your own mailbox.
When to use: each turn that should observe new mail; orchestrators that batch-poll many agents may prefer get_messages_summary (cheaper preview) or peek_inbox_version (counts only). For surveys that must NOT consume mail, set peek=true.
Behavior: returns messages addressed to you, ordered by priority then created_at newest-first. By default status='pending' returns un-read messages and atomically marks them read for THIS session (sessions are per-session_id; a fresh terminal re-sees previously-read messages, v2.0 final fix). Optional since ('1h' | '24h' | '7d' | ISO | 'all'); its DEFAULT DEPENDS ON STATUS: status='pending' defaults to 'all' (the action queue is never windowed unless you ask), history reads (all/history/read/resolved) default to '24h'. A pending read ALWAYS returns UNDELIVERED (never-drained) mail regardless of since (#198; 3.0.1). For a pending read total_pending is always the full, unwindowed queue, and when your since hid pending mail the response carries hidden_by_since: N. peek=true (v2.2.2) suppresses the read-MARK — the returned messages are not marked read for your session — but it is NOT side-effect-free: like any first view it stamps the observation cursor (seq). (Post-3.0.1 that observation no longer changes what a later drain returns.)
Returns: { messages: MessageRecord[], count, has_more, total_pending | total, hidden_by_since?, agent, filter, since, since_bound, acked?, resolved_count?, warning? }. since is the window actually applied (the status default when you gave none); since_bound is the ISO timestamp the relay filtered by (after resolving duration shorthands or 'session_start'). With ack=true on a pending drain, acked and resolved_count report what the database actually changed, never what was asked. If your agent has no current session (session_id NULL, e.g. after a token rotation), the drain still delivers and records the agent-level receipts (read_at, last_drain_at, resolves) and returns warning: { code: 'session_unbound', message }: unresolved mail comes back on the next drain until you re-register or resolve it.
Errors: AUTH_FAILED, VALIDATION (bad since format), RATE_LIMITED.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ack | No | v2.12.0: when true, permanently resolve the returned messages (atomic with the read-mark) so a fresh session won't re-surface them. Only applies to status='pending'. Default false = unchanged behavior. | |
| lane | No | Filter by message lane: 'all' (default), 'direct' (point-to-point only), or 'capability' (capability-routed FYI only). | all |
| peek | No | When true, skip the mark-as-read side effect so repeated status='pending' polls return the same messages. Default false (consume-once). | |
| limit | No | Max messages to return | |
| since | No | Time-window filter. Accepts duration ('15m'|'1h'|'24h'|'3d'), ISO8601 timestamp, 'session_start' sentinel, or 'all'/null for no bound. DEFAULT DEPENDS ON STATUS: status='pending' defaults to 'all' (the action queue is never windowed unless you ask); history reads (all/history/read/resolved) default to '24h'. On a pending read the bound applies only to mail this recipient has already seen: never-drained mail is always returned. When a window hides pending mail, the response says so in `hidden_by_since`. | |
| status | No | Filter by status. 'pending' (default) = unresolved + not-read-by-this-session (the action queue). 'read' = read by this session. 'all'/'history' = the full durable record incl. resolved. 'resolved' = only messages you've acked (v2.12.0). | pending |
| agent_name | Yes | Your agent name | |
| agent_token | No | Your agent token (from register_agent response). Optional here — also resolvable from RELAY_AGENT_TOKEN env or X-Agent-Token header. |