docs: align web/content/docs with actual SDK/CLI implementation#1172
Conversation
- Actions must be registered on an agent client (not the workspace client) to be exposed as MCP tools; fix quickstart, actions, events, event-handlers, orchestrating-with-actions examples - Fix envelope.from.handle -> envelope.from?.name (no handle field) - Fix action-handler caller agent.handle -> agent.name - Correct RelayEvent union, envelope, and event-name vocabulary in events - Fix delivery.failed listener to use nested session-event fields Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXcjNrVVjkgUakMmM89JgB
- agent-relay-mcp: real tool names (post_message, send_dm, reply_to_thread, add_reaction, check_inbox, mark_message_read), 'agent-relay mcp' has no subcommands and reads env, fix runtime action list, durable fallbacks - typescript-sdk: register is idempotent by default (strict opt-in), fix envelope.from.handle, MCP tool names, register action on agent client - fleets: handlers_live is on 'fleet nodes', not 'fleet status' Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXcjNrVVjkgUakMmM89JgB
- session-capabilities: real AgentSessionStatus (5 values), correct event
union field shapes (usage, session.*, message.*, terminal.screen, tool.*)
- delivery: real DeliveryRunner class + AgentDeliveryAdapter interface,
delivery events as nested session events, accurate retry behavior
- harnesses: real HarnessCreateContext/AgentIdentity, normalizeAgentIdentity,
create({relay}) returns a handle (no sendMessage) -> use relay.messages.send
- harness-driver: registerDriverActions takes ActionRegistry not relay; real
'local agent' CLI commands; agent.attach note
- remove reference-openclaw (no openclaw export exists) + nav entries and
dangling OpenClaw mentions
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXcjNrVVjkgUakMmM89JgB
- reference-cli: correct 'cloud connect <provider>' description, add cloud session, cloud worker, workspace active, and a Fleet command section - cli-overview: workflow file types include .js and .sh - introduction/typescript-sdk: real MCP tool names, register spawn action on agent client, caller.name instead of caller.handle - migration: envelope.from?.name - messaging: RelayMessage includes id - drop misleading OpenClaw harness mentions (no such harness exists) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXcjNrVVjkgUakMmM89JgB
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXcjNrVVjkgUakMmM89JgB
- workspaces: real RelayWorkspaceInfo/AgentIdentity shapes, register is idempotent by default, claude.create returns a handle not a client - webhooks: canonical outbound event names (agent.status.idle), drop unverifiable delivery.* names - migration: register idempotent-by-default wording Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXcjNrVVjkgUakMmM89JgB
📝 WalkthroughWalkthroughThis PR makes broad documentation-only corrections across 20+ Agent Relay docs pages: action registration is moved from the workspace client to agent clients, event/envelope/session type shapes are updated, MCP tool names are renamed, the fictional ChangesAgent Relay Docs Alignment
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request audits and updates the documentation across various MDX files to align with the actual SDK, CLI, and harness implementations. Key updates include clarifying that action registration must occur on an agent client to be exposed via MCP, correcting event and envelope shapes, updating MCP tool names, and removing the fictional reference-openclaw page. A review comment suggests adding a defensive check in the TypeScript SDK documentation example to ensure envelope.from?.name is defined before sending a message, preventing potential routing issues to @undefined.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (envelope.channel?.name === 'reviews') { | ||
| await planner.sendMessage({ | ||
| to: `@${envelope.from.handle}`, | ||
| to: `@${envelope.from?.name}`, | ||
| text: `Saw your message ${message.messageId}.`, | ||
| }); | ||
| } |
There was a problem hiding this comment.
In the message.created listener example, envelope.from is optional and can be undefined. Accessing envelope.from?.name inside the template literal without a guard will result in sending a message to the routing target "@undefined" if from is not present. Adding a defensive check for envelope.from?.name in the if condition prevents this issue.
if (envelope.channel?.name === 'reviews' && envelope.from?.name) {
await planner.sendMessage({
to: `@${envelope.from.name}`,
text: `Saw your message ${message.messageId}.`,
});
}
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 827b4adfef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Register on an **agent client** — the value returned by `relay.workspace.register(...)` or a harness | ||
| `create(...)`. The handler agent's identity is the descriptor's `handler_agent`, which is what registers the |
There was a problem hiding this comment.
Don't suggest harness handles can register actions
claude.create({ relay }) and the other prebuilt harness create calls return a HarnessAgent with identity plus status/tools, not a RelayAgentClient; the implementation builds it with createAgentHandle and it has no registerAction. Following this wording, users will try to expose an MCP action from a harness-created handle and get undefined instead of a relay-wired action. Limit this guidance to live agent clients from workspace.register/reconnect (or other APIs that actually return RelayAgentClient).
Useful? React with 👍 / 👎.
| await relay.messages.send({ | ||
| from: planner, | ||
| to: '#reviews', |
There was a problem hiding this comment.
Avoid documenting
from sends for tokenless harness handles
This example uses planner from claude.create({ relay }), but that handle does not carry an agent token; relay.messages.send({ from }) only switches to an agent-scoped client when from.token exists, otherwise it falls back to the workspace client, whose messages.send requires an agent client and throws. Users copying this prebuilt-harness example will not be able to send the channel message on behalf of the spawned agent.
Useful? React with 👍 / 👎.
| `registerDriverActions(actions, driver)` takes an `AgentRelayActions` registry, not the `AgentRelay` facade. | ||
| Pass the same registry to `createWorkspace` so the actions register on the relay (and `relay.action(...)` | ||
| listeners fire): |
There was a problem hiding this comment.
Don't claim driver actions are relay-registered
Passing the registry into createWorkspace does not publish actions to the relay: registerDriverActions(actions, driver) only calls ActionRegistry.register, while relay/MCP exposure requires the agent-scoped registerFacadeAction path that calls commands.register with a handler agent. With the documented setup, local relay.action(...) listeners can see local invocations, but separate agent-relay mcp clients will not discover agent.create/agent.release tools.
Useful? React with 👍 / 👎.
|
Preview deployed!
This preview will be cleaned up when the PR is merged or closed. |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
.agentworkforce/trajectories/completed/2026-06/traj_mnj85uiykwgm/summary.md (1)
5-5: 💤 Low valueAdd commas after year in dates.
Lines 5–6 follow month-day-year date format; AP style guide convention calls for a comma after the year when followed by additional time information.
🎨 Suggested fix
- > **Started:** June 19, 2026 at 04:19 AM - > **Completed:** June 19, 2026 at 04:44 AM + > **Started:** June 19, 2026, at 04:19 AM + > **Completed:** June 19, 2026, at 04:44 AMAlso applies to: 6-6
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.agentworkforce/trajectories/completed/2026-06/traj_mnj85uiykwgm/summary.md at line 5, The dates on lines 5 and 6 are missing commas after the year according to AP style guide conventions. In both instances where a date in month-day-year format is followed by time information, add a comma after the year (after 2026). Update "June 19, 2026 at 04:19 AM" to "June 19, 2026, at 04:19 AM" and apply the same formatting to the date on line 6.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/content/docs/delivery.mdx`:
- Around line 130-133: In the documentation for the `stop()` method behavior,
replace the phrase "ends the loop" with wording that clarifies it only requests
shutdown by setting a flag rather than immediately terminating the loop. The
method exits the loop after the next inbox subscription yields, not
synchronously, so the description should accurately reflect that `stop()`
initiates shutdown asynchronously rather than guaranteeing immediate termination
or disconnect behavior.
- Around line 176-179: The error message template in the delivery.failed
listener callback assumes deliveryId is always present, but DeliveryEvent
declares it as optional, which can result in "Delivery undefined failed..."
messages. Modify the text property of the planner.sendMessage call to use the
required messageId as the primary reference instead of deliveryId, optionally
including deliveryId only if it's available to avoid undefined values in the
message.
In `@web/content/docs/harness-driver.mdx`:
- Line 25: Line 25 of the harness-driver.mdx documentation incorrectly
references AgentRelayActions as the parameter type for registerDriverActions
function, but the example code and current API use ActionRegistry. Replace
AgentRelayActions with ActionRegistry on line 25 to align the documentation with
the actual implementation and maintain consistency throughout the example.
In `@web/content/docs/reference-cli.mdx`:
- Line 174: The command example in the table row for agent-relay cloud worker
contains escaped pipes with backslashes (register\|start\|status\|logs) which
render literally with the backslashes visible, making it invalid for users to
copy and paste. Remove the backslash escape characters from the pipe separators
so they appear as plain pipes, or alternatively split the single row into
multiple rows with individual command options (register, start, status, logs) to
make the syntax clear and copyable.
In `@web/content/docs/session-capabilities.mdx`:
- Around line 196-238: The documentation states on line 196 that every variant
of AgentSessionEvent carries optional fields `at?`, `agent?`, and `metadata?`,
but the `AgentSessionEvent` union type definition (lines 210-238) does not
include these fields in the type declaration. Update the `AgentSessionEvent`
type to include these three optional base fields in each union variant, either
by adding them explicitly to each variant or by using an intersection type with
a base type containing these fields, so the type definition matches the
documented contract.
In `@web/content/docs/workspaces.mdx`:
- Around line 94-95: The documentation currently instructs users to persist the
`planner.token` without explicitly marking it as a sensitive credential. Add
clear language in the workspaces.mdx file around the section mentioning
`planner.token` to explicitly call out that this token is a secret and must be
stored securely. Include guidance warning users not to hardcode, log, or commit
this token to source control, and recommend secure storage practices such as
environment variables or dedicated secret management systems.
---
Nitpick comments:
In @.agentworkforce/trajectories/completed/2026-06/traj_mnj85uiykwgm/summary.md:
- Line 5: The dates on lines 5 and 6 are missing commas after the year according
to AP style guide conventions. In both instances where a date in month-day-year
format is followed by time information, add a comma after the year (after 2026).
Update "June 19, 2026 at 04:19 AM" to "June 19, 2026, at 04:19 AM" and apply the
same formatting to the date on line 6.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b9d2f99a-fa13-4559-9da0-a24b2bdbacee
📒 Files selected for processing (26)
.agentworkforce/trajectories/completed/2026-06/traj_mnj85uiykwgm.trace.json.agentworkforce/trajectories/completed/2026-06/traj_mnj85uiykwgm/summary.md.agentworkforce/trajectories/completed/2026-06/traj_mnj85uiykwgm/trajectory.jsonweb/components/docs/DocsNav.tsxweb/content/docs/actions.mdxweb/content/docs/agent-relay-mcp.mdxweb/content/docs/cli-overview.mdxweb/content/docs/delivery.mdxweb/content/docs/event-handlers.mdxweb/content/docs/events.mdxweb/content/docs/fleets.mdxweb/content/docs/harness-driver.mdxweb/content/docs/harnesses.mdxweb/content/docs/introduction.mdxweb/content/docs/messaging.mdxweb/content/docs/migration.mdxweb/content/docs/orchestrating-with-actions.mdxweb/content/docs/quickstart.mdxweb/content/docs/reference-cli.mdxweb/content/docs/reference-openclaw.mdxweb/content/docs/session-capabilities.mdxweb/content/docs/threads.mdxweb/content/docs/typescript-sdk.mdxweb/content/docs/webhooks.mdxweb/content/docs/workspaces.mdxweb/lib/docs-nav.ts
💤 Files with no reviewable changes (3)
- web/content/docs/reference-openclaw.mdx
- web/components/docs/DocsNav.tsx
- web/lib/docs-nav.ts
| `start()` requires `messaging.capabilities.serverDeliveryState` and throws `RelayCapabilityError` otherwise. | ||
| It consumes `messaging.inbox.subscribe(...)`, calls the target for each item, then `ack`s, `defer`s, or | ||
| `fail`s the inbox item based on the returned `InjectionResult`. A thrown error is failed with `retry: true`; | ||
| an adapter that returns `status: 'failed'` is failed with `retry: false`. `stop()` ends the loop. |
There was a problem hiding this comment.
Clarify that stop() only requests shutdown.
The implementation only flips a stop flag and exits after the inbox subscription yields again, so “ends the loop” overpromises immediate termination/disconnect behavior.
Suggested wording
-`fail`s the inbox item based on the returned `InjectionResult`. A thrown error is failed with `retry: true`;
-an adapter that returns `status: 'failed'` is failed with `retry: false`. `stop()` ends the loop.
+`fail`s the inbox item based on the returned `InjectionResult`. A thrown error is failed with `retry: true`;
+an adapter that returns `status: 'failed'` is failed with `retry: false`. `stop()` requests shutdown; the
+loop exits before processing the next subscribed item.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| `start()` requires `messaging.capabilities.serverDeliveryState` and throws `RelayCapabilityError` otherwise. | |
| It consumes `messaging.inbox.subscribe(...)`, calls the target for each item, then `ack`s, `defer`s, or | |
| `fail`s the inbox item based on the returned `InjectionResult`. A thrown error is failed with `retry: true`; | |
| an adapter that returns `status: 'failed'` is failed with `retry: false`. `stop()` ends the loop. | |
| `start()` requires `messaging.capabilities.serverDeliveryState` and throws `RelayCapabilityError` otherwise. | |
| It consumes `messaging.inbox.subscribe(...)`, calls the target for each item, then `ack`s, `defer`s, or | |
| `fail`s the inbox item based on the returned `InjectionResult`. A thrown error is failed with `retry: true`; | |
| an adapter that returns `status: 'failed'` is failed with `retry: false`. `stop()` requests shutdown; the | |
| loop exits before processing the next subscribed item. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/content/docs/delivery.mdx` around lines 130 - 133, In the documentation
for the `stop()` method behavior, replace the phrase "ends the loop" with
wording that clarifies it only requests shutdown by setting a flag rather than
immediately terminating the loop. The method exits the loop after the next inbox
subscription yields, not synchronously, so the description should accurately
reflect that `stop()` initiates shutdown asynchronously rather than guaranteeing
immediate termination or disconnect behavior.
| relay.addListener('delivery.failed', (e) => | ||
| planner.sendMessage({ | ||
| to: '#ops', | ||
| text: `Delivery ${event.deliveryId} failed for ${event.messageId}: ${event.reason}.`, | ||
| text: `Delivery ${e.event.deliveryId} failed for ${e.event.messageId}: ${e.event.reason}.`, |
There was a problem hiding this comment.
Avoid assuming deliveryId is present.
DeliveryEvent declares deliveryId as optional, so this example can produce Delivery undefined failed... for valid events. Use the required messageId as the primary reference.
Suggested fix
relay.addListener('delivery.failed', (e) =>
planner.sendMessage({
to: '`#ops`',
- text: `Delivery ${e.event.deliveryId} failed for ${e.event.messageId}: ${e.event.reason}.`,
+ text: `Delivery failed for ${e.event.messageId}: ${e.event.reason}.`,
})
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| relay.addListener('delivery.failed', (e) => | |
| planner.sendMessage({ | |
| to: '#ops', | |
| text: `Delivery ${event.deliveryId} failed for ${event.messageId}: ${event.reason}.`, | |
| text: `Delivery ${e.event.deliveryId} failed for ${e.event.messageId}: ${e.event.reason}.`, | |
| relay.addListener('delivery.failed', (e) => | |
| planner.sendMessage({ | |
| to: '`#ops`', | |
| text: `Delivery failed for ${e.event.messageId}: ${e.event.reason}.`, | |
| }) | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/content/docs/delivery.mdx` around lines 176 - 179, The error message
template in the delivery.failed listener callback assumes deliveryId is always
present, but DeliveryEvent declares it as optional, which can result in
"Delivery undefined failed..." messages. Modify the text property of the
planner.sendMessage call to use the required messageId as the primary reference
instead of deliveryId, optionally including deliveryId only if it's available to
avoid undefined values in the message.
|
|
||
| Use the harness driver package when Agent Relay should manage the harness boundary for you. | ||
|
|
||
| `registerDriverActions(actions, driver)` takes an `AgentRelayActions` registry, not the `AgentRelay` facade. |
There was a problem hiding this comment.
Use the same registry type name as the example/API.
Line 25 says AgentRelayActions, but the example imports and instantiates ActionRegistry, and the PR objective calls out ActionRegistry as the corrected contract.
Suggested fix
-`registerDriverActions(actions, driver)` takes an `AgentRelayActions` registry, not the `AgentRelay` facade.
+`registerDriverActions(actions, driver)` takes an `ActionRegistry`, not the `AgentRelay` facade.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| `registerDriverActions(actions, driver)` takes an `AgentRelayActions` registry, not the `AgentRelay` facade. | |
| `registerDriverActions(actions, driver)` takes an `ActionRegistry`, not the `AgentRelay` facade. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/content/docs/harness-driver.mdx` at line 25, Line 25 of the
harness-driver.mdx documentation incorrectly references AgentRelayActions as the
parameter type for registerDriverActions function, but the example code and
current API use ActionRegistry. Replace AgentRelayActions with ActionRegistry on
line 25 to align the documentation with the actual implementation and maintain
consistency throughout the example.
| | `agent-relay cloud logs` | Show cloud run logs. | | ||
| | `agent-relay cloud sync` | Sync local state with cloud. | | ||
| | `agent-relay cloud cancel` | Cancel a cloud run. | | ||
| | `agent-relay cloud worker register\|start\|status\|logs` | Manage cloud workers. | |
There was a problem hiding this comment.
Fix escaped pipes in the cloud worker command example.
Line 174 currently renders backslashes as part of the command. Use plain separators (or split into separate rows) so users can copy valid syntax.
Suggested doc fix
-| `agent-relay cloud worker register\|start\|status\|logs` | Manage cloud workers. |
+| `agent-relay cloud worker register|start|status|logs` | Manage cloud workers. |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | `agent-relay cloud worker register\|start\|status\|logs` | Manage cloud workers. | | |
| | `agent-relay cloud worker register|start|status|logs` | Manage cloud workers. | |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/content/docs/reference-cli.mdx` at line 174, The command example in the
table row for agent-relay cloud worker contains escaped pipes with backslashes
(register\|start\|status\|logs) which render literally with the backslashes
visible, making it invalid for users to copy and paste. Remove the backslash
escape characters from the pipe separators so they appear as plain pipes, or
alternatively split the single row into multiple rows with individual command
options (register, start, status, logs) to make the syntax clear and copyable.
| Every variant also carries the optional `AgentSessionEventBase` fields `at?`, `agent?`, and `metadata?`. | ||
|
|
||
| ```ts | ||
| type TranscriptChunk = { | ||
| id: string; | ||
| at: Date; | ||
| at?: Date | string; | ||
| role: 'agent' | 'user' | 'system' | 'tool'; | ||
| content: string; | ||
| sequence: number; | ||
| sequence?: number; | ||
| metadata?: Record<string, unknown>; | ||
| }; | ||
|
|
||
| type SessionCaller = AgentIdentity | { name: string; id?: string; type?: 'agent' | 'human' | 'system' }; | ||
|
|
||
| type AgentSessionEvent = | ||
| | { type: 'status.changed'; status: AgentStatus; previousStatus?: AgentStatus; reason?: string } | ||
| | { type: 'status.changed'; status: AgentSessionStatus; previousStatus?: AgentSessionStatus; reason?: string } | ||
| | { type: 'status.idle' | 'status.active' | 'status.blocked' | 'status.waiting' | 'status.offline'; reason?: string } | ||
| | { type: 'message.received' | 'message.sent'; message: RelayMessage } | ||
| | { type: 'delivery.accepted' | 'delivery.delivered'; messageId: string; deliveryId?: string } | ||
| | { type: 'delivery.deferred'; messageId: string; deliveryId?: string; availableAt: Date | string; reason?: string } | ||
| | { type: 'delivery.failed'; messageId: string; deliveryId?: string; reason: string; retryable?: boolean } | ||
| | { type: 'tool.called'; run?: string; tool: string; input?: unknown } | ||
| | { type: 'tool.completed'; run?: string; tool: string; output?: unknown; durationMs?: number } | ||
| | { type: 'tool.failed'; run?: string; tool: string; error: string; retryable?: boolean } | ||
| | { type: 'tool.output'; run?: string; tool: string; output: string } | ||
| | { type: 'message.received'; messageId: string; deliveryId?: string } | ||
| | { type: 'message.sent'; messageId: string } | ||
| | { type: 'delivery.accepted'; deliveryId: string; messageId: string } | ||
| | { type: 'delivery.delivered'; deliveryId: string; messageId: string } | ||
| | { type: 'delivery.deferred'; deliveryId: string; messageId: string; availableAt: Date | string; reason?: string } | ||
| | { type: 'delivery.failed'; deliveryId: string; messageId: string; reason: string; retryable?: boolean } | ||
| | { type: 'action.invoked'; action: string; invocationId: string } | ||
| | { type: 'action.completed'; action: string; invocationId: string; durationMs?: number } | ||
| | { type: 'action.failed'; action: string; invocationId: string; error: string; retryable?: boolean } | ||
| | { type: 'action.denied'; action: string; invocationId: string; reason: string } | ||
| | { type: 'tool.failed'; run?: string; tool: string; error: string; durationMs?: number } | ||
| | { type: 'tool.output'; run?: string; tool?: string; output: unknown } | ||
| | { type: 'action.invoked'; action: string; input?: unknown; caller?: SessionCaller } | ||
| | { type: 'action.completed'; action: string; output?: unknown; caller?: SessionCaller; durationMs?: number } | ||
| | { type: 'action.failed'; action: string; error: string; caller?: SessionCaller; durationMs?: number } | ||
| | { type: 'action.denied'; action: string; reason?: string; caller?: SessionCaller } | ||
| | { type: 'transcript.chunk'; chunk: TranscriptChunk } | ||
| | { type: 'file.changed'; path: string; operation: 'create' | 'update' | 'delete'; diff?: string } | ||
| | { type: 'command.started'; command: string; cwd?: string } | ||
| | { type: 'command.completed'; command: string; exitCode?: number; durationMs?: number } | ||
| | { type: 'command.failed'; command: string; error: string; exitCode?: number } | ||
| | { type: 'command.started'; commandId?: string; command: string; cwd?: string } | ||
| | { type: 'command.completed'; commandId?: string; command?: string; exitCode?: number; durationMs?: number } | ||
| | { type: 'command.failed'; commandId?: string; command?: string; error: string; exitCode?: number; durationMs?: number } | ||
| | { type: 'terminal.output'; stream?: 'stdout' | 'stderr' | 'combined'; text: string } | ||
| | { type: 'terminal.screen'; text: string; rows?: number; cols?: number } | ||
| | { type: 'usage.updated'; tokens?: number; costUsd?: number; metadata?: Record<string, unknown> } | ||
| | { type: 'session.started'; sessionId: string } | ||
| | { type: 'session.released'; sessionId: string; reason?: string } | ||
| | { type: 'session.resumed'; sessionId: string } | ||
| | { type: 'session.forked'; sessionId: string; parentSessionId: string } | ||
| | { type: 'log'; level: 'debug' | 'info' | 'warn' | 'error'; message: string } | ||
| | { type: 'terminal.screen'; text: string; rows?: number; columns?: number } | ||
| | { type: 'usage.updated'; usage: Record<string, number | string | boolean | null> } | ||
| | { type: 'session.started'; reason?: string } | ||
| | { type: 'session.released'; reason?: string } | ||
| | { type: 'session.resumed'; reason?: string } | ||
| | { type: 'session.forked'; child: AgentIdentity } | ||
| | { type: 'log'; level?: 'debug' | 'info' | 'warn' | 'error'; message: string } | ||
| | { type: 'error'; error: string; code?: string; retryable?: boolean }; |
There was a problem hiding this comment.
Make the documented base fields part of the shown union type.
Line 196 says every variant carries at?, agent?, and metadata?, but the AgentSessionEvent union on Lines 210-238 does not include them. This leaves the contract self-contradictory for readers.
Proposed doc-type fix
+type AgentSessionEventBase = {
+ at?: Date | string;
+ agent?: AgentIdentity;
+ metadata?: Record<string, unknown>;
+};
+
type AgentSessionEvent =
- | { type: 'status.changed'; status: AgentSessionStatus; previousStatus?: AgentSessionStatus; reason?: string }
+ | (AgentSessionEventBase & { type: 'status.changed'; status: AgentSessionStatus; previousStatus?: AgentSessionStatus; reason?: string })
// ...apply AgentSessionEventBase to each variant🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/content/docs/session-capabilities.mdx` around lines 196 - 238, The
documentation states on line 196 that every variant of AgentSessionEvent carries
optional fields `at?`, `agent?`, and `metadata?`, but the `AgentSessionEvent`
union type definition (lines 210-238) does not include these fields in the type
declaration. Update the `AgentSessionEvent` type to include these three optional
base fields in each union variant, either by adding them explicitly to each
variant or by using an intersection type with a base type containing these
fields, so the type definition matches the documented contract.
| Pass `{ strict: true }` to reject an existing name. Persist an agent's token off its live client | ||
| (`planner.token`) and rehydrate it later in a fresh process with `relay.workspace.reconnect({ apiToken })`. |
There was a problem hiding this comment.
Call out secure storage for persisted agent tokens.
This now tells users to persist planner.token; explicitly mark it as a secret so it does not end up in logs, docs, or source control.
Suggested fix
-Pass `{ strict: true }` to reject an existing name. Persist an agent's token off its live client
-(`planner.token`) and rehydrate it later in a fresh process with `relay.workspace.reconnect({ apiToken })`.
+Pass `{ strict: true }` to reject an existing name. Persist an agent's token off its live client
+(`planner.token`) in secure secret storage, and rehydrate it later in a fresh process with
+`relay.workspace.reconnect({ apiToken })`.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Pass `{ strict: true }` to reject an existing name. Persist an agent's token off its live client | |
| (`planner.token`) and rehydrate it later in a fresh process with `relay.workspace.reconnect({ apiToken })`. | |
| Pass `{ strict: true }` to reject an existing name. Persist an agent's token off its live client | |
| (`planner.token`) in secure secret storage, and rehydrate it later in a fresh process with | |
| `relay.workspace.reconnect({ apiToken })`. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/content/docs/workspaces.mdx` around lines 94 - 95, The documentation
currently instructs users to persist the `planner.token` without explicitly
marking it as a sensitive credential. Add clear language in the workspaces.mdx
file around the section mentioning `planner.token` to explicitly call out that
this token is a secret and must be stored securely. Include guidance warning
users not to hardcode, log, or commit this token to source control, and
recommend secure storage practices such as environment variables or dedicated
secret management systems.
Audited all 27 docs in
web/content/docs/against the actual implementation (packages/sdk/src,packages/cli/src, harnesses, harness-driver). Every API name, signature, event, MCP tool, CLI command, and example was verified against source; unverifiable/fictional content was removed.Cross-cutting correctness bugs
relay.registerAction), whichagent-relay.ts:256confirms stays in-process and is never exposed via MCP. Fixed to register on an agent client in quickstart, actions, events, event-handlers, orchestrating-with-actions, agent-relay-mcp, typescript-sdk.envelope.from.handledoesn't exist —RelayMessageSenderis{ id?, name? }. Fixed tofrom?.namethroughout.agent.handledoesn't exist — the caller is{ name, id?, type? }. Fixed toagent.name.claude.create({ relay })returns a handle, not a messaging client (nosendMessage). Fixed examples to userelay.messages.send({ from }).registeris idempotent by default (strict: trueto reject), not "rejects existing names." Fixed in workspaces, typescript-sdk, migration.Type/shape definitions rewritten to match source
session-capabilities: realAgentSessionStatus(5 values), correctedAgentSessionEventunion fields (usage, session., message., terminal.screencolumns, tool.*).delivery: realDeliveryRunnerclass +AgentDeliveryAdapterinterface (documenteddeliver/retry/flushdon't exist); delivery events as nested session events.harnesses: realHarnessCreateContext/AgentIdentity;normalizeAgentIdentity(ctx.agent)instead of nonexistentctx.ids.agent(...).events: correctedRelayEventunion, envelope schema, event-name vocabulary (agent.status.idle).Commands/tools
agent-relay-mcp: real tool names (post_message,send_dm,reply_to_thread,add_reaction,check_inbox,mark_message_read);agent-relay mcphas nostart/installsubcommands; removed nonexistentflush_deliveries/list_events.harness-driver:registerDriverActions(actions, driver)takes anActionRegistry, notrelay; thedriverCLI group doesn't exist (replaced with reallocal agentcommands).reference-cli: fixedcloud connect <provider>, addedcloud session,cloud worker,workspace active, and a Fleet section.fleets:handlers_liveis onfleet nodes, notfleet status.Deleted
reference-openclaw.mdx— documented a nonexistentopenclawexport; no OpenClaw code exists inpackages/orcrates/. Removed the page, nav entries, icon mapping, and dangling OpenClaw mentions.Remaining unverifiable areas
{ message, author }) is enforced by the relay server (not in this repo); the SDK side is verified. Left as the documented external contract.🤖 Generated with Claude Code
Generated by Claude Code