From 61860d0772876e53e825d377eca41f97f5eca027 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-sync[bot]" Date: Fri, 10 Apr 2026 20:22:56 +0000 Subject: [PATCH] chore(sync): mirror docs from openclaw/openclaw@6783bef7ed5827c8818679395c91478aa3041d45 --- .openclaw-sync/source.json | 4 +- docs/.generated/config-baseline.sha256 | 8 +- .../.generated/plugin-sdk-api-baseline.sha256 | 4 +- docs/concepts/model-providers.md | 4 + docs/docs.json | 13 + docs/help/testing.md | 46 ++++ docs/plugins/sdk-agent-harness.md | 224 ++++++++++++++++++ docs/plugins/sdk-overview.md | 30 +-- docs/plugins/sdk-provider-plugins.md | 7 + docs/plugins/sdk-runtime.md | 10 +- 10 files changed, 326 insertions(+), 24 deletions(-) create mode 100644 docs/plugins/sdk-agent-harness.md diff --git a/.openclaw-sync/source.json b/.openclaw-sync/source.json index 98e6d116d..1224e4f25 100644 --- a/.openclaw-sync/source.json +++ b/.openclaw-sync/source.json @@ -1,5 +1,5 @@ { "repository": "openclaw/openclaw", - "sha": "905f19230a1379ae3a4f3230a42acf55c5f3c8b1", - "syncedAt": "2026-04-10T18:36:08.874Z" + "sha": "6783bef7ed5827c8818679395c91478aa3041d45", + "syncedAt": "2026-04-10T20:22:56.304Z" } diff --git a/docs/.generated/config-baseline.sha256 b/docs/.generated/config-baseline.sha256 index c8e85b02d..9324a7056 100644 --- a/docs/.generated/config-baseline.sha256 +++ b/docs/.generated/config-baseline.sha256 @@ -1,4 +1,4 @@ -a962c1d7ddffa15f2333854f77b03da4f6db07fada16f288377ee1daf50afc08 config-baseline.json -3c8455d44a63d495ad295d2c9d76fed7a190b80344dabaa0e78ba433bf2d253b config-baseline.core.json -df55c673a1cdbebc4fe68baaaf9d0d4289313be5034be92f0d510726a086b1d6 config-baseline.channel.json -3f6fccab66a9abe7e1dd412fb01b13b944ed24edbe09df55ada3323acc7f76fe config-baseline.plugin.json +c2705b6fbb297a6f06aefa6036db71aa5dbfea5a21ec3dafd53ed631cdc558f9 config-baseline.json +b8e245d02a00b696af2b4f0447553dd3b5bb98ca805aca650fb2ce5c0487eacb config-baseline.core.json +e1f94346a8507ce3dec763b598e79f3bb89ff2e33189ce977cc87d3b05e71c1d config-baseline.channel.json +9153501720ea74f9356432a011fa9b41c9b700084bfe0d156feb5647624b35ad config-baseline.plugin.json diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256 index 130d44d63..ba7e736b4 100644 --- a/docs/.generated/plugin-sdk-api-baseline.sha256 +++ b/docs/.generated/plugin-sdk-api-baseline.sha256 @@ -1,2 +1,2 @@ -8a754603a721c3816772a0a4f44b83a19547163ad52ff1b9f18eaaeeaf0de6d4 plugin-sdk-api-baseline.json -40539cf99459c77dab1d6e72af2e3f05cafb77f2c49af5fa210c78dc231592b4 plugin-sdk-api-baseline.jsonl +cceabd98fbc368e04aba61e1d3712fe0f86749dc3872e4b9ba057784e29a8559 plugin-sdk-api-baseline.json +de31f5f77bda7163bed395b9669861cb64c514cf1666324e406b7882d84dee7c plugin-sdk-api-baseline.jsonl diff --git a/docs/concepts/model-providers.md b/docs/concepts/model-providers.md index ca712a650..d6425205a 100644 --- a/docs/concepts/model-providers.md +++ b/docs/concepts/model-providers.md @@ -50,6 +50,10 @@ For model selection rules, see [/concepts/models](/concepts/models). family, transcript/tooling quirks, transport/cache hints). It is not the same as the [public capability model](/plugins/architecture#public-capability-model) which describes what a plugin registers (text inference, speech, etc.). +- The bundled `codex` provider is paired with the bundled Codex agent harness. + Use `codex/gpt-*` when you want Codex-owned login, model discovery, native + thread resume, and app-server execution. Plain `openai/gpt-*` refs continue + to use the OpenAI provider and the normal OpenClaw provider transport. ## Plugin-owned provider behavior diff --git a/docs/docs.json b/docs/docs.json index e0c4f75ea..101eb99c7 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -1142,6 +1142,7 @@ "plugins/sdk-overview", "plugins/sdk-entrypoints", "plugins/sdk-runtime", + "plugins/sdk-agent-harness", "plugins/sdk-setup", "plugins/sdk-testing", "plugins/manifest", @@ -2511,6 +2512,7 @@ "ja-JP/plugins/sdk-overview", "ja-JP/plugins/sdk-entrypoints", "ja-JP/plugins/sdk-runtime", + "ja-JP/plugins/sdk-agent-harness", "ja-JP/plugins/sdk-setup", "ja-JP/plugins/sdk-testing", "ja-JP/plugins/manifest", @@ -3265,6 +3267,7 @@ "es/plugins/sdk-overview", "es/plugins/sdk-entrypoints", "es/plugins/sdk-runtime", + "es/plugins/sdk-agent-harness", "es/plugins/sdk-setup", "es/plugins/sdk-testing", "es/plugins/manifest", @@ -4019,6 +4022,7 @@ "pt-BR/plugins/sdk-overview", "pt-BR/plugins/sdk-entrypoints", "pt-BR/plugins/sdk-runtime", + "pt-BR/plugins/sdk-agent-harness", "pt-BR/plugins/sdk-setup", "pt-BR/plugins/sdk-testing", "pt-BR/plugins/manifest", @@ -4773,6 +4777,7 @@ "ko/plugins/sdk-overview", "ko/plugins/sdk-entrypoints", "ko/plugins/sdk-runtime", + "ko/plugins/sdk-agent-harness", "ko/plugins/sdk-setup", "ko/plugins/sdk-testing", "ko/plugins/manifest", @@ -5527,6 +5532,7 @@ "de/plugins/sdk-overview", "de/plugins/sdk-entrypoints", "de/plugins/sdk-runtime", + "de/plugins/sdk-agent-harness", "de/plugins/sdk-setup", "de/plugins/sdk-testing", "de/plugins/manifest", @@ -6281,6 +6287,7 @@ "fr/plugins/sdk-overview", "fr/plugins/sdk-entrypoints", "fr/plugins/sdk-runtime", + "fr/plugins/sdk-agent-harness", "fr/plugins/sdk-setup", "fr/plugins/sdk-testing", "fr/plugins/manifest", @@ -7035,6 +7042,7 @@ "ar/plugins/sdk-overview", "ar/plugins/sdk-entrypoints", "ar/plugins/sdk-runtime", + "ar/plugins/sdk-agent-harness", "ar/plugins/sdk-setup", "ar/plugins/sdk-testing", "ar/plugins/manifest", @@ -7789,6 +7797,7 @@ "it/plugins/sdk-overview", "it/plugins/sdk-entrypoints", "it/plugins/sdk-runtime", + "it/plugins/sdk-agent-harness", "it/plugins/sdk-setup", "it/plugins/sdk-testing", "it/plugins/manifest", @@ -8543,6 +8552,7 @@ "tr/plugins/sdk-overview", "tr/plugins/sdk-entrypoints", "tr/plugins/sdk-runtime", + "tr/plugins/sdk-agent-harness", "tr/plugins/sdk-setup", "tr/plugins/sdk-testing", "tr/plugins/manifest", @@ -9297,6 +9307,7 @@ "uk/plugins/sdk-overview", "uk/plugins/sdk-entrypoints", "uk/plugins/sdk-runtime", + "uk/plugins/sdk-agent-harness", "uk/plugins/sdk-setup", "uk/plugins/sdk-testing", "uk/plugins/manifest", @@ -10051,6 +10062,7 @@ "id/plugins/sdk-overview", "id/plugins/sdk-entrypoints", "id/plugins/sdk-runtime", + "id/plugins/sdk-agent-harness", "id/plugins/sdk-setup", "id/plugins/sdk-testing", "id/plugins/manifest", @@ -10805,6 +10817,7 @@ "pl/plugins/sdk-overview", "pl/plugins/sdk-entrypoints", "pl/plugins/sdk-runtime", + "pl/plugins/sdk-agent-harness", "pl/plugins/sdk-setup", "pl/plugins/sdk-testing", "pl/plugins/manifest", diff --git a/docs/help/testing.md b/docs/help/testing.md index 072fa368f..4caaa478e 100644 --- a/docs/help/testing.md +++ b/docs/help/testing.md @@ -390,6 +390,51 @@ Docker notes: - It sources `~/.profile`, stages the matching CLI auth material into the container, installs `acpx` into a writable npm prefix, then installs the requested live CLI (`@anthropic-ai/claude-code`, `@openai/codex`, or `@google/gemini-cli`) if missing. - Inside Docker, the runner sets `OPENCLAW_LIVE_ACP_BIND_ACPX_COMMAND=$HOME/.npm-global/bin/acpx` so acpx keeps provider env vars from the sourced profile available to the child harness CLI. +## Live: Codex app-server harness smoke + +- Goal: validate the plugin-owned Codex harness through the normal gateway + `agent` method: + - load the bundled `codex` plugin + - select `OPENCLAW_AGENT_RUNTIME=codex` + - send a first gateway agent turn to `codex/gpt-5.4` + - send a second turn to the same OpenClaw session and verify the app-server + thread can resume +- Test: `src/gateway/gateway-codex-harness.live.test.ts` +- Enable: `OPENCLAW_LIVE_CODEX_HARNESS=1` +- Default model: `codex/gpt-5.4` +- Optional image probe: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1` +- Optional MCP/tool probe: `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1` +- Auth: `OPENAI_API_KEY` from the shell/profile, plus optional copied + `~/.codex/auth.json` and `~/.codex/config.toml` + +Local recipe: + +```bash +source ~/.profile +OPENCLAW_LIVE_CODEX_HARNESS=1 \ + OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=1 \ + OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=1 \ + OPENCLAW_LIVE_CODEX_HARNESS_MODEL=codex/gpt-5.4 \ + pnpm test:live -- src/gateway/gateway-codex-harness.live.test.ts +``` + +Docker recipe: + +```bash +source ~/.profile +pnpm test:docker:live-codex-harness +``` + +Docker notes: + +- The Docker runner lives at `scripts/test-live-codex-harness-docker.sh`. +- It sources the mounted `~/.profile`, passes `OPENAI_API_KEY`, copies Codex CLI + auth files when present, installs `@openai/codex` into a writable mounted npm + prefix, stages the source tree, then runs only the Codex-harness live test. +- Docker enables the image and MCP/tool probes by default. Set + `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0` or + `OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0` when you need a narrower debug run. + ### Recommended live recipes Narrow, explicit allowlists are fastest and least flaky: @@ -618,6 +663,7 @@ The live-model Docker runners also bind-mount only the needed CLI auth homes (or - Direct models: `pnpm test:docker:live-models` (script: `scripts/test-live-models-docker.sh`) - ACP bind smoke: `pnpm test:docker:live-acp-bind` (script: `scripts/test-live-acp-bind-docker.sh`) - CLI backend smoke: `pnpm test:docker:live-cli-backend` (script: `scripts/test-live-cli-backend-docker.sh`) +- Codex app-server harness smoke: `pnpm test:docker:live-codex-harness` (script: `scripts/test-live-codex-harness-docker.sh`) - Gateway + dev agent: `pnpm test:docker:live-gateway` (script: `scripts/test-live-gateway-models-docker.sh`) - Open WebUI live smoke: `pnpm test:docker:openwebui` (script: `scripts/e2e/openwebui-docker.sh`) - Onboarding wizard (TTY, full scaffolding): `pnpm test:docker:onboard` (script: `scripts/e2e/onboard-docker.sh`) diff --git a/docs/plugins/sdk-agent-harness.md b/docs/plugins/sdk-agent-harness.md new file mode 100644 index 000000000..721587f71 --- /dev/null +++ b/docs/plugins/sdk-agent-harness.md @@ -0,0 +1,224 @@ +--- +title: "Agent Harness Plugins" +sidebarTitle: "Agent Harness" +summary: "Experimental SDK surface for plugins that replace the low level embedded agent executor" +read_when: + - You are changing the embedded agent runtime or harness registry + - You are registering an agent harness from a bundled or trusted plugin + - You need to understand how the Codex plugin relates to model providers +--- + +# Agent Harness Plugins + +An **agent harness** is the low level executor for one prepared OpenClaw agent +turn. It is not a model provider, not a channel, and not a tool registry. + +Use this surface only for bundled or trusted native plugins. The contract is +still experimental because the parameter types intentionally mirror the current +embedded runner. + +## When to use a harness + +Register an agent harness when a model family has its own native session +runtime and the normal OpenClaw provider transport is the wrong abstraction. + +Examples: + +- a native coding-agent server that owns threads and compaction +- a local CLI or daemon that must stream native plan/reasoning/tool events +- a model runtime that needs its own resume id in addition to the OpenClaw + session transcript + +Do **not** register a harness just to add a new LLM API. For normal HTTP or +WebSocket model APIs, build a [provider plugin](/plugins/sdk-provider-plugins). + +## What core still owns + +Before a harness is selected, OpenClaw has already resolved: + +- provider and model +- runtime auth state +- thinking level and context budget +- the OpenClaw transcript/session file +- workspace, sandbox, and tool policy +- channel reply callbacks and streaming callbacks +- model fallback and live model switching policy + +That split is intentional. A harness runs a prepared attempt; it does not pick +providers, replace channel delivery, or silently switch models. + +## Register a harness + +**Import:** `openclaw/plugin-sdk/agent-harness` + +```typescript +import type { AgentHarness } from "openclaw/plugin-sdk/agent-harness"; +import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"; + +const myHarness: AgentHarness = { + id: "my-harness", + label: "My native agent harness", + + supports(ctx) { + return ctx.provider === "my-provider" + ? { supported: true, priority: 100 } + : { supported: false }; + }, + + async runAttempt(params) { + // Start or resume your native thread. + // Use params.prompt, params.tools, params.images, params.onPartialReply, + // params.onAgentEvent, and the other prepared attempt fields. + return await runMyNativeTurn(params); + }, +}; + +export default definePluginEntry({ + id: "my-native-agent", + name: "My Native Agent", + description: "Runs selected models through a native agent daemon.", + register(api) { + api.registerAgentHarness(myHarness); + }, +}); +``` + +## Selection policy + +OpenClaw chooses a harness after provider/model resolution: + +1. `OPENCLAW_AGENT_RUNTIME=` forces a registered harness with that id. +2. `OPENCLAW_AGENT_RUNTIME=pi` forces the built-in PI harness. +3. `OPENCLAW_AGENT_RUNTIME=auto` asks registered harnesses if they support the + resolved provider/model. +4. If no registered harness matches, OpenClaw uses PI. + +Forced plugin harness failures surface as run failures. In `auto` mode, +OpenClaw may fall back to PI when the selected plugin harness fails before a +turn has produced side effects. + +The bundled Codex plugin registers `codex` as its harness id. For compatibility, +`codex-app-server` and `app-server` also resolve to that same harness when you +set `OPENCLAW_AGENT_RUNTIME` manually. + +## Provider plus harness pairing + +Most harnesses should also register a provider. The provider makes model refs, +auth status, model metadata, and `/model` selection visible to the rest of +OpenClaw. The harness then claims that provider in `supports(...)`. + +The bundled Codex plugin follows this pattern: + +- provider id: `codex` +- user model refs: `codex/gpt-5.4`, `codex/gpt-5.2`, or another model returned + by the Codex app server +- harness id: `codex` +- auth: synthetic provider availability, because the Codex harness owns the + native Codex login/session +- app-server request: OpenClaw sends the bare model id to Codex and lets the + harness talk to the native app-server protocol + +The Codex plugin is additive. Plain `openai/gpt-*` refs remain OpenAI provider +refs and continue to use the normal OpenClaw provider path. Select `codex/gpt-*` +when you want Codex-managed auth, Codex model discovery, native threads, and +Codex app-server execution. `/model` can switch among the Codex models returned +by the Codex app server without requiring OpenAI provider credentials. + +OpenClaw requires Codex app-server `0.118.0` or newer. The Codex plugin checks +the app-server initialize handshake and blocks older or unversioned servers so +OpenClaw only runs against the protocol surface it has been tested with. + +## Harness selection policy + +By default, OpenClaw runs embedded agents with `agents.defaults.embeddedHarness` +set to `{ runtime: "auto", fallback: "pi" }`. In `auto` mode, registered plugin +harnesses can claim a provider/model pair. If none match, or if an auto-selected +plugin harness fails before producing output, OpenClaw falls back to PI. + +Set `fallback: "none"` when you need to prove that a plugin harness is the only +runtime being exercised: + +```json +{ + "agents": { + "defaults": { + "model": "codex/gpt-5.4", + "embeddedHarness": { + "runtime": "codex", + "fallback": "none" + } + } + } +} +``` + +Per-agent overrides use the same shape: + +```json +{ + "agents": { + "defaults": { + "embeddedHarness": { + "runtime": "auto", + "fallback": "pi" + } + }, + "list": [ + { + "id": "codex-only", + "model": "codex/gpt-5.4", + "embeddedHarness": { + "runtime": "codex", + "fallback": "none" + } + } + ] + } +} +``` + +`OPENCLAW_AGENT_RUNTIME` still overrides the configured runtime. Use +`OPENCLAW_AGENT_HARNESS_FALLBACK=none` to disable PI fallback from the +environment. + +## Native sessions and transcript mirror + +A harness may keep a native session id, thread id, or daemon-side resume token. +Keep that binding explicitly associated with the OpenClaw session, and keep +mirroring user-visible assistant/tool output into the OpenClaw transcript. + +The OpenClaw transcript remains the compatibility layer for: + +- channel-visible session history +- transcript search and indexing +- switching back to the built-in PI harness on a later turn +- generic `/new`, `/reset`, and session deletion behavior + +If your harness stores a sidecar binding, implement `reset(...)` so OpenClaw can +clear it when the owning OpenClaw session is reset. + +## Tool and media results + +Core constructs the OpenClaw tool list and passes it into the prepared attempt. +When a harness executes a dynamic tool call, return the tool result back through +the harness result shape instead of sending channel media yourself. + +This keeps text, image, video, music, TTS, approval, and messaging-tool outputs +on the same delivery path as PI-backed runs. + +## Current limitations + +- The public import path is generic, but some attempt/result type aliases still + carry `Pi` names for compatibility. +- Third-party harness installation is experimental. Prefer provider plugins + until you need a native session runtime. +- Harness switching is supported across turns. Do not switch harnesses in the + middle of a turn after native tools, approvals, assistant text, or message + sends have started. + +## Related + +- [SDK Overview](/plugins/sdk-overview) +- [Runtime Helpers](/plugins/sdk-runtime) +- [Provider Plugins](/plugins/sdk-provider-plugins) +- [Model Providers](/concepts/model-providers) diff --git a/docs/plugins/sdk-overview.md b/docs/plugins/sdk-overview.md index ace11b48d..512d1cbc5 100644 --- a/docs/plugins/sdk-overview.md +++ b/docs/plugins/sdk-overview.md @@ -219,6 +219,7 @@ explicitly promotes one as public. | `plugin-sdk/models-provider-runtime` | `/models` command/provider reply helpers | | `plugin-sdk/skill-commands-runtime` | Skill command listing helpers | | `plugin-sdk/native-command-registry` | Native command registry/build/serialize helpers | + | `plugin-sdk/agent-harness` | Experimental trusted-plugin surface for low-level agent harnesses: harness types, active-run steer/abort helpers, OpenClaw tool bridge helpers, and attempt result utilities | | `plugin-sdk/provider-zai-endpoint` | Z.AI endpoint detection helpers | | `plugin-sdk/infra-runtime` | System event/heartbeat helpers | | `plugin-sdk/collection-runtime` | Small bounded cache helpers | @@ -302,20 +303,21 @@ methods: ### Capability registration -| Method | What it registers | -| ------------------------------------------------ | -------------------------------- | -| `api.registerProvider(...)` | Text inference (LLM) | -| `api.registerCliBackend(...)` | Local CLI inference backend | -| `api.registerChannel(...)` | Messaging channel | -| `api.registerSpeechProvider(...)` | Text-to-speech / STT synthesis | -| `api.registerRealtimeTranscriptionProvider(...)` | Streaming realtime transcription | -| `api.registerRealtimeVoiceProvider(...)` | Duplex realtime voice sessions | -| `api.registerMediaUnderstandingProvider(...)` | Image/audio/video analysis | -| `api.registerImageGenerationProvider(...)` | Image generation | -| `api.registerMusicGenerationProvider(...)` | Music generation | -| `api.registerVideoGenerationProvider(...)` | Video generation | -| `api.registerWebFetchProvider(...)` | Web fetch / scrape provider | -| `api.registerWebSearchProvider(...)` | Web search | +| Method | What it registers | +| ------------------------------------------------ | ------------------------------------- | +| `api.registerProvider(...)` | Text inference (LLM) | +| `api.registerAgentHarness(...)` | Experimental low-level agent executor | +| `api.registerCliBackend(...)` | Local CLI inference backend | +| `api.registerChannel(...)` | Messaging channel | +| `api.registerSpeechProvider(...)` | Text-to-speech / STT synthesis | +| `api.registerRealtimeTranscriptionProvider(...)` | Streaming realtime transcription | +| `api.registerRealtimeVoiceProvider(...)` | Duplex realtime voice sessions | +| `api.registerMediaUnderstandingProvider(...)` | Image/audio/video analysis | +| `api.registerImageGenerationProvider(...)` | Image generation | +| `api.registerMusicGenerationProvider(...)` | Music generation | +| `api.registerVideoGenerationProvider(...)` | Video generation | +| `api.registerWebFetchProvider(...)` | Web fetch / scrape provider | +| `api.registerWebSearchProvider(...)` | Web search | ### Tools and commands diff --git a/docs/plugins/sdk-provider-plugins.md b/docs/plugins/sdk-provider-plugins.md index d76c741b5..3f8dc76c7 100644 --- a/docs/plugins/sdk-provider-plugins.md +++ b/docs/plugins/sdk-provider-plugins.md @@ -20,6 +20,13 @@ API key auth, and dynamic model resolution. structure and manifest setup. + + Provider plugins add models to OpenClaw's normal inference loop. If the model + must run through a native agent daemon that owns threads, compaction, or tool + events, pair the provider with an [agent harness](/plugins/sdk-agent-harness) + instead of putting daemon protocol details in core. + + ## Walkthrough diff --git a/docs/plugins/sdk-runtime.md b/docs/plugins/sdk-runtime.md index e0a731976..94105634a 100644 --- a/docs/plugins/sdk-runtime.md +++ b/docs/plugins/sdk-runtime.md @@ -50,9 +50,9 @@ const timeoutMs = api.runtime.agent.resolveAgentTimeoutMs(cfg); // Ensure workspace exists await api.runtime.agent.ensureAgentWorkspace(cfg); -// Run an embedded Pi agent +// Run an embedded agent turn const agentDir = api.runtime.agent.resolveAgentDir(cfg); -const result = await api.runtime.agent.runEmbeddedPiAgent({ +const result = await api.runtime.agent.runEmbeddedAgent({ sessionId: "my-plugin:task-1", runId: crypto.randomUUID(), sessionFile: path.join(agentDir, "sessions", "my-plugin-task-1.jsonl"), @@ -62,6 +62,12 @@ const result = await api.runtime.agent.runEmbeddedPiAgent({ }); ``` +`runEmbeddedAgent(...)` is the neutral helper for starting a normal OpenClaw +agent turn from plugin code. It uses the same provider/model resolution and +agent-harness selection as channel-triggered replies. + +`runEmbeddedPiAgent(...)` remains as a compatibility alias. + **Session store helpers** are under `api.runtime.agent.session`: ```typescript