You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Streamline the plugin to focus on its core purpose:
- Session affinity (session_id, sticky_key metadata injection)
- X-Session-Id transport header
- Requester runtime metadata (sanitized for TaaS proxy)
- Autorouter response-header capture + taas.autorouter.lastRoute gateway RPC
- Add activation.onStartup for reliable plugin loading
Removed dead-end features that belong in the TaaS proxy layer, not
the OpenClaw plugin:
- Trash sweeper (periodic run-directory cleanup)
- Stuck-run status writer (JSON status files)
- Zombie auto-abort (detect idle runs, emit chat.abort)
- Background timer scheduler (setInterval orchestration)
These features were either no-ops (zombie abort had no SDK dispatch
capability) or redundant with the TaaS proxy's own lifecycle management.
An [OpenClaw](https://openclaw.ai) provider plugin that maximises prompt-cache hit rates when using [CloudSigma TaaS](https://www.cloudsigma.com) as your LLM provider.
3
+
CloudSigma TaaS affinity provider hook for OpenClaw.
4
4
5
-
It injects a stable, per-conversation session ID into every outbound request so TaaS can pin your conversation to the same upstream slot (OAuth token, Bedrock region, or Claude Code node) from the very first turn — giving you consistent prompt-cache reuse instead of cold starts on every message.
5
+
This plugin is intentionally narrow after the Claude Code Direction-2 lane update. It does **not** lease requester bridges, poll for bridge work, invoke requester-local tools, rewrite OpenAI tool payloads, or run OpenClaw maintenance sidecars.
6
6
7
-
The plugin is intentionally narrow: requester-side tool execution is handled by Claude Code, TaaS, and the OpenClaw gateway Direction-2 path. This plugin does**not** lease requester bridges, poll for bridge work, invoke local tools, or alter OpenAI tool payloads.
7
+
## What it does
8
8
9
-
---
9
+
For requests routed through the `cloudsigma` or `cloudsigma-staging` provider IDs, the plugin:
10
10
11
-
## The problem it solves
11
+
- derives a stable affinity session ID with the form `oc:<sha256-prefix>`
12
+
- injects `metadata.session_id` when absent
13
+
- injects `metadata.sticky_key` when absent
14
+
- injects a sanitized `metadata.requester_runtime` envelope when absent
15
+
- injects transport header `X-Session-Id`
16
+
- captures TaaS autorouter response headers
17
+
- exposes the latest route capture via gateway method `taas.autorouter.lastRoute`
12
18
13
-
TaaS routes LLM requests across a pool of upstream slots. Without a session signal, it uses heuristics to guess which requests belong to the same conversation:
19
+
## Startup compatibility
14
20
15
-
| Method | Confidence | Works when |
16
-
|---|---:|---|
17
-
| Tool-use ID chain | 1.0 | Tool-result follow-up turns only |
18
-
| Structural inference | 0.85 | Mid-conversation, after a few turns |
19
-
| New session fallback | 0.30 | First turn — no prior context |
20
-
21
-
That **0.30 confidence on turn 1** means the first message in every conversation is likely routed to a random slot, breaking prompt-cache continuity right from the start.
21
+
The manifest explicitly asks OpenClaw to import the plugin at gateway startup:
22
22
23
-
This plugin passes a stable `session_id` derived from your OpenClaw workspace so TaaS short-circuits heuristic matching and achieves **confidence 1.0 from turn 1**.
This is required because gateway RPC handlers must be attached during gateway startup. Provider/lazy activation is not enough for `taas.autorouter.lastRoute` to be present in the live gateway dispatch table.
26
33
27
-
## How it works
34
+
## Request metadata
28
35
29
-
OpenClaw's `wrapStreamFn` hook intercepts the outbound request payload before it is sent to TaaS. The plugin adds session affinity fields plus a small sanitized requester runtime envelope:
36
+
Example injected metadata:
30
37
31
38
```json
32
39
{
33
40
"metadata": {
34
-
"session_id": "oc:edebc39a82a8a041",
35
-
"sticky_key": "oc:edebc39a82a8a041",
41
+
"session_id": "oc:0123456789abcdef",
42
+
"sticky_key": "oc:0123456789abcdef",
36
43
"requester_runtime": {
37
-
"schema_version": "2026-06-03",
38
-
"source": "openclaw-token-cache-optimizer",
39
-
"session_key": "oc:edebc39a82a8a041",
40
-
"openclaw_session_id": "oc:edebc39a82a8a041",
44
+
"schema_version": "2026-06-04",
45
+
"source": "openclaw-taas-affinity",
46
+
"session_key": "oc:0123456789abcdef",
47
+
"openclaw_session_id": "oc:0123456789abcdef",
41
48
"requester_host_id": "host:1a2b3c4d5e6f7890",
42
-
"repo_name": "my-repo",
49
+
"repo_name": "example-repo",
43
50
"git_branch_hint": "dev",
44
51
"git_dirty_hint": false,
45
52
"provider": "cloudsigma",
46
53
"model_id": "cloudsigma/auto",
47
-
"session_source_hint": "source:4ae2870a2e73027c",
54
+
"session_source_hint": "source:1a2b3c4d5e6f7890",
48
55
"tool_execution": "direction_2_gateway",
49
56
"metadata_classification": {
50
57
"identifiers": "hashed",
@@ -57,231 +64,121 @@ OpenClaw's `wrapStreamFn` hook intercepts the outbound request payload before it
57
64
}
58
65
```
59
66
60
-
-`session_id` — read by TaaS's OpenAI and Codex affinity paths.
61
-
-`sticky_key` — additionally read by the Anthropic substrate routing layer.
62
-
-`requester_runtime` — safe advisory hints for downstream routing and diagnostics.
63
-
-`X-Session-Id` — injected by `resolveTransportTurnState` for transports that support per-turn native headers.
64
-
65
-
All metadata fields are no-overwrite: if the caller already supplied `metadata.session_id`, `metadata.sticky_key`, or `metadata.requester_runtime`, the plugin leaves them intact.
67
+
All metadata fields are no-overwrite. If the caller already supplied `metadata.session_id`, `metadata.sticky_key`, or `metadata.requester_runtime`, the plugin leaves them intact.
66
68
67
-
### Requester runtime metadata
69
+
The plugin does not include raw local paths (`workspace_dir`, `agent_dir`, `repo_root_hint`), environment variables, tokens, git remotes, full git status output, diffs, or arbitrary provider `extraParams`.
68
70
69
-
The runtime envelope is intentionally small and sanitized. By default it contains:
Requester-side tool execution is handled outside this plugin by the Claude Code / TaaS / OpenClaw Direction-2 path.
77
74
78
-
It does **not** include raw local paths (`workspace_dir`, `agent_dir`, `repo_root_hint`) by default. It also never includes environment variables, tokens, git remotes, full status output, diffs, or arbitrary provider `extraParams`. Git probes are bounded with a short timeout.
75
+
The plugin intentionally leaves these payload structures untouched:
79
76
80
-
### Tool execution model: Direction-2
77
+
- OpenAI `tools`
78
+
-`tool_choice`
79
+
- assistant `tool_calls`
80
+
-`role: "tool"` continuation messages
81
81
82
-
Requester-side tools are handled outside this plugin by Claude Code / TaaS / OpenClaw gateway Direction-2. Consequently this plugin:
82
+
It also does not inject:
83
83
84
-
- does not call `/internal/requester-bridges/leases`
85
-
- does not inject `requester_runtime.available_bridges`
86
-
- does not set `capture_mode: "bridge_capable"`
87
-
- does not poll `/internal/requester-bridges/poll` or post `/internal/requester-bridges/results`
88
-
- does not invoke requester-local `/tools/invoke`
89
-
- does not intercept OpenAI `tools`, `tool_calls`, or `role: "tool"` messages
84
+
-`requester_runtime.available_bridges`
85
+
-`capture_mode: "bridge_capable"`
86
+
- bridge operation names such as `requester.tool.invoke`, `openclaw.tool.invoke`, `bridge.ping`, or `bridge.echo`
90
87
91
-
### Session ID derivation
88
+
##Autorouter route capture
92
89
93
-
The ID is a SHA-256 hash of the session source, truncated to 16 hex chars and prefixed `oc:`. The plugin walks through a tier list to find the best available source:
90
+
TaaS may return response headers such as:
94
91
95
-
| Tier | Source | Notes |
96
-
|---|---|---|
97
-
| 1 |`ctx.workspaceDir` (explicit) | Best signal — populated for main agent and many subagents |
98
-
| 2 |`globalThis[pluginRegistryState].workspaceDir`| Parent agent workspace via plugin registry |
99
-
| 3 |`process.env.OPENCLAW_SESSION_ID`| If OpenClaw sets this env var for sub-agents in future |
100
-
| 4 |`process.env.OPENCLAW_AGENT_ID` / `OPENCLAW_RUN_ID`| Any stable per-agent env var |
101
-
| 5 |`OPENCLAW_STATE_DIR` hash | Per-installation fallback — least specific |
92
+
-`X-TaaS-Autorouted: true`
93
+
-`X-TaaS-Autorouter-Model`
94
+
-`X-TaaS-Autorouter-Mode`
95
+
-`X-TaaS-Autorouter-Algorithm-Source`
96
+
-`X-TaaS-Thinking-Applied`
97
+
-`X-TaaS-Routed-Context-Window`
102
98
103
-
| Property | Detail |
104
-
|---|---|
105
-
|**Stable**| Same value for every API turn within one conversation |
106
-
|**Unique**| Different workspaces / env vars → different IDs |
107
-
|**Resets on `/new`**| New conversation = new workspace = new ID |
108
-
|**Namespaced**|`oc:` prefix avoids collision with Claude Code and other TaaS clients |
99
+
The plugin stores the latest bounded capture per affinity session and per derived OpenClaw agent ID.
109
100
110
-
### Autorouter capture
101
+
Query latest route by agent:
111
102
112
-
The wrapper captures TaaS `X-TaaS-*` response headers for autorouted requests and exposes the most recent route via the gateway RPC:
113
-
114
-
```text
115
-
taas.autorouter.lastRoute
103
+
```bash
104
+
openclaw gateway call taas.autorouter.lastRoute \
105
+
--params '{"agentId":"new-agent-2"}' \
106
+
--json
116
107
```
117
108
118
-
Callers can query by `workspaceDir`, direct `sessionId`, or `agentId`. Captured values include the autorouted model, algorithm/mode, algorithm source, thinking level applied, and routed context window.
119
-
120
-
### Sub-agent behaviour
121
-
122
-
OpenClaw sub-agents run in isolated processes and may not receive a `workspaceDir` in their `wrapStreamFn` context. The tier fallback system ensures sub-agents always get a deterministic session ID:
123
-
124
-
1.**If the sub-agent has a workspace** (Tier 1) — derives a unique ID from it.
125
-
2.**If the parent agent workspace is visible** via globalThis (Tier 2) — reuses the parent's ID.
126
-
3.**If OpenClaw injects env vars** (Tiers 3–4) — uses those for a stable per-agent ID.
127
-
4.**Last resort** (Tier 5) — falls back to the state dir hash.
128
-
129
-
#### Debug logging
130
-
131
-
Set `OPENCLAW_DEBUG=1` (or `NODE_ENV=development`) to emit the session ID source on each request:
- Requires the provider plugin hooks exposed via `openclaw/plugin-sdk/core`, including `wrapStreamFn`, `hookAliases`, and `resolveTransportTurnState`.
144
-
-**Node.js** 22+
145
-
-**TaaS** with session-affinity short-circuit support (commit `61a9960`+, April 2026)
146
-
- A CloudSigma account with TaaS access
147
-
148
-
Older OpenClaw builds may fail to load the plugin or may load it without applying the transport/header hook. Upgrade OpenClaw before deploying this plugin to production instances.
149
-
150
-
---
151
-
152
-
## Installation
153
-
154
-
### Option 1 - npm install
117
+
Query by workspace path, deriving the same affinity session ID as the wrapper:
Requester bridge variables such as `TAAS_REQUESTER_BRIDGE_PLUGIN_ENABLED`, `TAAS_REQUESTER_BRIDGE_LEASE_URL`, and `TAAS_REQUESTER_BRIDGE_POLL_INTERVAL_MS` are obsolete and ignored by this plugin version.
278
-
279
-
---
280
-
281
-
## Contributing
282
-
283
-
Issues and PRs welcome. The core logic lives in [`index.ts`](./index.ts).
0 commit comments