@embassys/ambassador 0.2.9 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +18 -7
  2. package/dist/agent-capabilities.d.ts +13 -0
  3. package/dist/agent-capabilities.js +80 -2
  4. package/dist/agent-capabilities.js.map +1 -1
  5. package/dist/ambassador-options.d.ts +4 -0
  6. package/dist/ambassador-options.js +7 -1
  7. package/dist/ambassador-options.js.map +1 -1
  8. package/dist/central-enrollment.js +1 -5
  9. package/dist/central-enrollment.js.map +1 -1
  10. package/dist/cli.js +17 -2
  11. package/dist/cli.js.map +1 -1
  12. package/dist/credential-store.d.ts +4 -4
  13. package/dist/credential-store.js +6 -98
  14. package/dist/credential-store.js.map +1 -1
  15. package/dist/delivery-profile.d.ts +10 -7
  16. package/dist/delivery-profile.js +62 -44
  17. package/dist/delivery-profile.js.map +1 -1
  18. package/dist/direct-delivery.d.ts +3 -1
  19. package/dist/direct-delivery.js +114 -12
  20. package/dist/direct-delivery.js.map +1 -1
  21. package/dist/gateway-application.d.ts +4 -0
  22. package/dist/gateway-application.js +16 -6
  23. package/dist/gateway-application.js.map +1 -1
  24. package/dist/gateway-paths.d.ts +2 -0
  25. package/dist/gateway-paths.js +2 -0
  26. package/dist/gateway-paths.js.map +1 -1
  27. package/dist/guided-registration.d.ts +2 -1
  28. package/dist/guided-registration.js +18 -7
  29. package/dist/guided-registration.js.map +1 -1
  30. package/dist/process-lock.js +1 -0
  31. package/dist/process-lock.js.map +1 -1
  32. package/dist/sqlite-artifact.d.ts +9 -1
  33. package/dist/sqlite-artifact.js +23 -8
  34. package/dist/sqlite-artifact.js.map +1 -1
  35. package/dist/webhook-delivery.d.ts +2 -0
  36. package/dist/webhook-delivery.js +101 -22
  37. package/dist/webhook-delivery.js.map +1 -1
  38. package/dist/webhook-secret-store.d.ts +16 -0
  39. package/dist/webhook-secret-store.js +49 -0
  40. package/dist/webhook-secret-store.js.map +1 -0
  41. package/dist/windows-access-control.d.ts +6 -0
  42. package/dist/windows-access-control.js +161 -0
  43. package/dist/windows-access-control.js.map +1 -0
  44. package/docs/development-reset.md +28 -0
  45. package/docs/getting-started-claude.md +3 -3
  46. package/docs/getting-started-codex.md +3 -3
  47. package/docs/getting-started-gemini.md +1 -1
  48. package/docs/getting-started-hermes.md +78 -26
  49. package/docs/getting-started-openclaw.md +92 -31
  50. package/docs/live-qualification.md +74 -2
  51. package/package.json +2 -1
@@ -3,49 +3,101 @@
3
3
  ## Before you start
4
4
 
5
5
  - Install Node.js `>=24.19.0 <25`.
6
- - Install and authenticate the latest Hermes Agent release.
6
+ - Install and authenticate Hermes Agent.
7
7
  - Make sure `hermes-acp` is on `PATH` for direct delivery.
8
8
  - Ambassador never receives your provider credential.
9
9
 
10
10
  ## Set up direct delivery
11
11
 
12
- 1. From the directory Hermes may access, keep Ambassador running:
12
+ 1. From the directory Hermes may access, keep the latest Ambassador running:
13
13
 
14
14
  ```sh
15
15
  npx --yes @embassys/ambassador@latest start
16
16
  ```
17
17
 
18
- 2. Add `http://127.0.0.1:8787/mcp` as a Streamable HTTP MCP server in Hermes's
19
- normal MCP configuration. Do not configure authentication.
18
+ 2. Add the endpoint printed by Ambassador as an unauthenticated Streamable
19
+ HTTP MCP server:
20
+
21
+ ```sh
22
+ hermes mcp add ambassador \
23
+ --url http://127.0.0.1:8787/mcp \
24
+ --connect-timeout 15
25
+ ```
26
+
27
+ Replace the URL if Ambassador printed a different loopback port. Do not
28
+ configure authentication.
20
29
  3. Start or restart Hermes so it sees the MCP server.
21
- 4. Ask Hermes to register your email; it calls Ambassador's `register_agent`
30
+ 4. Ask Hermes to register your email. It calls Ambassador's `register_agent`
22
31
  tool.
23
32
  5. Choose **Send directly to this Hermes agent**.
24
33
  6. Enter the six-digit code sent to your email.
25
34
 
26
- Ambassador will launch `hermes-acp` when a central message arrives. That is a
27
- new gateway-managed session, not the chat used for registration.
35
+ Ambassador launches `hermes-acp` when a central message arrives. That is a new
36
+ gateway-managed session, not the chat used for registration. Reported versions
37
+ are diagnostic only: Ambassador tries the fixed ACP v1 command and exact
38
+ `hermes-agent` identity, then reports a bounded startup, initialization,
39
+ session, or delivery failure if they are incompatible.
40
+
41
+ ## Set up webhook delivery
28
42
 
29
- ## Use a webhook instead
43
+ Hermes has a native generic webhook receiver. Configure one owner-controlled
44
+ route that uses the same value for Ambassador's bearer and HMAC V2 contract:
45
+
46
+ 1. With Ambassador running, choose **Send to a webhook** during registration.
47
+ Ambassador responds with:
48
+
49
+ ```sh
50
+ npx --yes @embassys/ambassador@latest webhook-secret
51
+ ```
52
+
53
+ Ambassador creates the secret, encrypts it in its own owner-only state, and
54
+ displays it. Repeating the command displays the same value; it does not
55
+ rotate it.
56
+
57
+ 2. Enable Hermes webhooks with `WEBHOOK_ENABLED=true` and your chosen
58
+ `WEBHOOK_PORT` in Hermes's owner-only `.hermes/.env`. Add this route to
59
+ `.hermes/webhook_subscriptions.json`, replacing both placeholders with the
60
+ displayed value and preserving any existing routes:
61
+
62
+ ```json
63
+ {
64
+ "embassys": {
65
+ "description": "Embassys Ambassador",
66
+ "events": [],
67
+ "filters": [
68
+ {
69
+ "field": "headers.Authorization",
70
+ "equals": "Bearer PASTE_AMBASSADOR_SECRET_HERE"
71
+ }
72
+ ],
73
+ "prompt": "",
74
+ "skills": [],
75
+ "deliver": "log",
76
+ "secret": "PASTE_AMBASSADOR_SECRET_HERE"
77
+ }
78
+ }
79
+ ```
80
+
81
+ Keep the file mode `0600`. An empty prompt passes the complete canonical
82
+ JSON to the model. The route uses Hermes's normal tool configuration, so
83
+ keep the Ambassador MCP server enabled there.
84
+
85
+ 3. Start or restart `hermes gateway run`. The local receiver URL is normally:
86
+
87
+ ```text
88
+ http://127.0.0.1:8644/webhooks/embassys
89
+ ```
30
90
 
31
- - Before step 1, set the receiver secret in the same shell:
91
+ Use the actual configured port. A non-loopback receiver must use an HTTPS
92
+ URL.
32
93
 
33
- ```sh
34
- export AMBASSADOR_WEBHOOK_SECRET="$(
35
- node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
36
- )"
37
- ```
94
+ 4. Retry `register_agent` with webhook selected and that URL. MCP carries only
95
+ `delivery.mode` and `delivery.url`; it never carries the secret or a secret
96
+ name.
38
97
 
39
- - During registration, choose **Send to a webhook**.
40
- - Give Hermes the HTTPS webhook URL and the variable name
41
- `AMBASSADOR_WEBHOOK_SECRET`.
42
- - Hermes supplies `delivery.url` and `delivery.secret_env`; it never receives
43
- the secret value.
98
+ Hermes validates the bearer filter and HMAC V2 timestamp/signature before its
99
+ model runs. A webhook `2xx` proves custody only. Keep both Hermes and
100
+ Ambassador running until the model calls `respond_to_permission` or
101
+ `submit_action_result` and the requester receives the correlated response.
44
102
 
45
- Ambassador selects this profile by the exact known MCP client name, then tries
46
- the fixed `hermes-acp` ACP v1 contract for direct delivery. Reported client and
47
- agent versions are diagnostic only. An incompatible release fails at startup,
48
- ACP initialization, session creation, or delivery instead of being rejected by
49
- a version list. See
50
- [Qualification](qualification.md) for the artifact-specific compatibility
51
- evidence.
103
+ For local reruns, see [Reset local test state](development-reset.md).
@@ -3,49 +3,110 @@
3
3
  ## Before you start
4
4
 
5
5
  - Install Node.js `>=24.19.0 <25`.
6
- - Install and authenticate the latest OpenClaw release.
6
+ - Install and authenticate OpenClaw.
7
7
  - Make sure `openclaw` is on `PATH` for direct delivery.
8
8
  - Ambassador never receives your provider credential.
9
9
 
10
10
  ## Set up direct delivery
11
11
 
12
- 1. From the directory OpenClaw may access, keep Ambassador running:
12
+ 1. From the directory OpenClaw may access, keep the latest Ambassador running:
13
13
 
14
14
  ```sh
15
15
  npx --yes @embassys/ambassador@latest start
16
16
  ```
17
17
 
18
- 2. Add `http://127.0.0.1:8787/mcp` as a Streamable HTTP MCP server in
19
- OpenClaw's normal MCP configuration. Do not configure authentication.
18
+ 2. Add the endpoint printed by Ambassador as an unauthenticated Streamable
19
+ HTTP MCP server, then probe it:
20
+
21
+ ```sh
22
+ openclaw mcp set ambassador \
23
+ '{"url":"http://127.0.0.1:8787/mcp","transport":"streamable-http","enabled":true}'
24
+ openclaw mcp doctor ambassador --probe
25
+ ```
26
+
27
+ Replace the URL if Ambassador printed a different loopback port. Do not
28
+ configure authentication.
20
29
  3. Start or restart OpenClaw so it sees the MCP server.
21
- 4. Ask OpenClaw to register your email; it calls Ambassador's `register_agent`
22
- tool.
30
+ 4. Ask OpenClaw to register your email. It calls Ambassador's
31
+ `register_agent` tool.
23
32
  5. Choose **Send directly to this OpenClaw agent**.
24
33
  6. Enter the six-digit code sent to your email.
25
34
 
26
- Ambassador will launch `openclaw acp` when a central message arrives. OpenClaw
35
+ Ambassador launches `openclaw acp` when a central message arrives. OpenClaw
27
36
  does not accept session MCP injection, so keep the provider-side MCP entry from
28
- step 2 configured.
29
-
30
- ## Use a webhook instead
31
-
32
- - Before step 1, set the receiver secret in the same shell:
33
-
34
- ```sh
35
- export AMBASSADOR_WEBHOOK_SECRET="$(
36
- node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
37
- )"
38
- ```
39
-
40
- - During registration, choose **Send to a webhook**.
41
- - Give OpenClaw the HTTPS webhook URL and the variable name
42
- `AMBASSADOR_WEBHOOK_SECRET`.
43
- - OpenClaw supplies `delivery.url` and `delivery.secret_env`; it never receives
44
- the secret value.
45
-
46
- Ambassador selects this profile by the exact known MCP client name, then tries
47
- the fixed `openclaw acp` ACP v1 contract for direct delivery. Reported client
48
- and agent versions are diagnostic only. An incompatible release fails at
49
- startup, ACP initialization, session creation, or delivery instead of being
50
- rejected by a version list. See
51
- [Qualification](qualification.md) for compatibility evidence.
37
+ step 2 configured. Reported versions are diagnostic only: Ambassador tries the
38
+ fixed ACP v1 command and exact `openclaw-acp` identity, then reports a bounded
39
+ startup, initialization, session, or delivery failure if they are incompatible.
40
+
41
+ ## Set up webhook delivery
42
+
43
+ 1. With `ambassador start` still running, choose **Send to a webhook** during
44
+ registration. Ambassador responds with this setup command:
45
+
46
+ ```sh
47
+ npx --yes @embassys/ambassador@latest webhook-secret
48
+ ```
49
+
50
+ Ambassador creates the secret, encrypts it in its own owner-only state, and
51
+ displays it. Repeating the command displays the same value; it does not
52
+ rotate it.
53
+
54
+ 2. Open OpenClaw's native hook configuration:
55
+
56
+ ```sh
57
+ openclaw config patch --stdin
58
+ ```
59
+
60
+ Paste this block with the displayed secret, then send end-of-file with
61
+ `Ctrl-D`:
62
+
63
+ ```json5
64
+ {
65
+ hooks: {
66
+ enabled: true,
67
+ token: "PASTE_AMBASSADOR_SECRET_HERE",
68
+ path: "/hooks",
69
+ allowedAgentIds: ["main"],
70
+ allowRequestSessionKey: false,
71
+ },
72
+ }
73
+ ```
74
+
75
+ OpenClaw stores `hooks.token` in its owner-only configuration. Its native
76
+ hook does not accept a SecretRef for this field. The secret does not enter a
77
+ command argument, shell history, or model prompt.
78
+
79
+ 3. Validate the configuration and restart the OpenClaw gateway:
80
+
81
+ ```sh
82
+ openclaw config validate
83
+ openclaw gateway restart
84
+ ```
85
+
86
+ If the gateway runs in the foreground, stop and start that process instead.
87
+ The local receiver URL is normally:
88
+
89
+ ```text
90
+ http://127.0.0.1:18789/hooks/agent
91
+ ```
92
+
93
+ Use the actual configured gateway port. A non-loopback receiver must use an
94
+ HTTPS URL.
95
+
96
+ 4. Retry `register_agent` with webhook selected and that URL. MCP carries only
97
+ `delivery.mode` and `delivery.url`; it never carries the secret or a secret
98
+ name.
99
+
100
+ Ambassador sends OpenClaw's native agent-hook body with the complete central
101
+ message inside a fixed untrusted-input prompt. It selects agent `main`, uses an
102
+ isolated session, suppresses announcement delivery, authenticates with the
103
+ generated bearer secret, and sends the central message ID as the idempotency
104
+ key. A webhook `200` proves that OpenClaw admitted the run. It does not prove
105
+ that the model later called Ambassador MCP. End-to-end checks must wait for the
106
+ correlated permission or action response.
107
+
108
+ If OpenClaw admits the run but the action times out, check that the agent's own
109
+ provider credential and Ambassador MCP entry are available to the gateway.
110
+ Ambassador does not receive either credential.
111
+
112
+ For local reruns, see [Reset local test state](development-reset.md).
@@ -11,7 +11,7 @@ general reply operations. It does test the deployed, action-specific
11
11
  The runner covers the current package name, guided registration, one
12
12
  full-message webhook target, and one direct target. The default direct target
13
13
  is the deterministic mock ACP agent. Separately confirmed modes use the fixed
14
- Codex or Hermes profiles. Real-provider modes use isolated provider
14
+ Codex, Hermes, or OpenClaw profiles. Real-provider modes use isolated provider
15
15
  configuration copies. Installed-version probes are observational; production
16
16
  requires the exact known client and ACP agent names and then tries the fixed
17
17
  ACP v1 contract.
@@ -33,7 +33,8 @@ ACP v1 contract.
33
33
  direct profile. Prove a dual-mode profile advertises direct as its default;
34
34
  prove a direct-only profile proceeds without a delivery question.
35
35
  4. Receive and use both verification emails without persisting their codes.
36
- 5. Restart and prove encrypted credential and nonsecret profile loading.
36
+ 5. Restart and prove encrypted credential, encrypted webhook-secret, and
37
+ nonsecret profile loading.
37
38
  6. Prove valid Bearer plus DPoP requests and the negative DPoP matrix.
38
39
  7. Validate the live action catalog against the recorded fixture schemas.
39
40
  8. Request and decide one synthetic `get_phone_number` permission.
@@ -113,6 +114,38 @@ mode starts Hermes's authenticated generic route,
113
114
  requires its bearer filter and native HMAC V2 validation, and suppresses
114
115
  provider output. Delete the isolated home after every attempt.
115
116
 
117
+ For OpenClaw, prepare an owner-only temporary home containing copies of
118
+ `.openclaw/openclaw.json`, `.openclaw/state/openclaw.sqlite`, and
119
+ `.openclaw/agents/main/agent/openclaw-agent.sqlite`. Copy only the provider
120
+ credential used by that OpenClaw agent; for the tested Codex-backed agent this
121
+ also means `.codex/auth.json` and its provider configuration. Use SQLite's
122
+ backup operation for live database copies. Put the installed `openclaw` on
123
+ `PATH`, then choose one fixed mode:
124
+
125
+ ```sh
126
+ export AMBASSADOR_OPENCLAW_QUALIFICATION_HOME=/absolute/path/to/isolated/home
127
+ export AMBASSADOR_LIVE_DIRECT_AGENT=openclaw-direct
128
+ export AMBASSADOR_CONFIRM_LIVE_QUALIFICATION=run-live-qualification-with-real-openclaw-direct-and-two-disposable-mailosaur-identities
129
+ pnpm run qualify:live
130
+ ```
131
+
132
+ or:
133
+
134
+ ```sh
135
+ export AMBASSADOR_OPENCLAW_QUALIFICATION_HOME=/absolute/path/to/isolated/home
136
+ export AMBASSADOR_LIVE_DIRECT_AGENT=openclaw-webhook
137
+ export AMBASSADOR_CONFIRM_LIVE_QUALIFICATION=run-live-qualification-with-real-openclaw-webhook-and-two-disposable-mailosaur-identities
138
+ pnpm run qualify:live
139
+ ```
140
+
141
+ The runner rejects the ordinary OpenClaw home. It configures Ambassador MCP
142
+ only in the copy. Direct mode launches the fixed `openclaw acp` profile and
143
+ requires ACP v1 plus exact agent name `openclaw-acp`. Webhook mode creates the
144
+ secret through the packed Ambassador CLI, writes it to the copied
145
+ OpenClaw configuration through `openclaw config patch --stdin`, enables the
146
+ native `/hooks/agent` route for `main`, and runs the real OpenClaw gateway. It
147
+ does not install a plugin. Delete the isolated home after every attempt.
148
+
116
149
  ## Required report
117
150
 
118
151
  Record only:
@@ -264,6 +297,45 @@ These observations approve the source registry's exact Hermes ACP 0.20.5
264
297
  entry. They do not show that published Ambassador 0.2.7 supports Hermes 0.20.5
265
298
  direct mode. Ambassador 0.2.8 contains the candidate change.
266
299
 
300
+ ## OpenClaw observations
301
+
302
+ On 2026-09-03, authenticated OpenClaw 2026.8.2 ran on macOS arm64 with Node
303
+ 24.19.0 and passed the complete live correlated-result flow in direct and
304
+ webhook modes with the Ambassador 0.2.10 candidate. Both modes registered and
305
+ verified two disposable identities, reloaded encrypted Ambassador state after
306
+ restart, exercised live REST and DPoP plus the deployed action catalog, and
307
+ completed the synthetic phone-number permission and action round trip. The
308
+ real OpenClaw model called `respond_to_permission` and called
309
+ `submit_action_result` exactly once. The controlled requester received the
310
+ correlated final response, and local completion or webhook custody preceded
311
+ central acknowledgement. Final candidate digests and the separate mode results
312
+ are recorded in [Delivery qualification](qualification.md).
313
+
314
+ Direct mode proved ACP v1 initialization through fixed `openclaw acp`, exact
315
+ agent name `openclaw-acp`, provider-side Ambassador MCP configuration, real
316
+ model execution, and correlated submission. An earlier isolation attempt
317
+ omitted the credential for the agent's configured provider backend; OpenClaw
318
+ then ended the model turn with an authentication failure before any Ambassador
319
+ MCP call. Adding that owner-only credential to the isolated copy made the
320
+ unchanged direct flow pass. This was an isolation-fixture failure, not an
321
+ Ambassador ACP incompatibility.
322
+
323
+ Webhook mode proved the package-shipped route's bearer and exact-body HMAC V2
324
+ checks, bounded custody queue, real model execution, Ambassador MCP calls, and
325
+ the final response. Earlier receiver attempts returned `202` and Ambassador
326
+ correctly acknowledged central, but OpenClaw made no model or MCP call. The
327
+ first implementation omitted required embedded-run fields. After those were
328
+ added, the detached run inherited the HTTP handler's released work-admission
329
+ lease and OpenClaw rejected it with the safe class `GatewayDrainingError`. A
330
+ plugin-service queue created outside the request context removes that false
331
+ drain path. A `202` still proves custody only; the passing run waited for the
332
+ model calls and requester response.
333
+
334
+ All OpenClaw attempts used an owner-only isolated home. Mailosaur messages,
335
+ temporary Ambassador state, the OpenClaw copy, and copied provider credentials
336
+ were removed after qualification. No provider output or message content was
337
+ recorded.
338
+
267
339
  ## Earlier direct observation
268
340
 
269
341
  On 2026-09-02, real Codex had already passed delivery, injected Ambassador MCP
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embassys/ambassador",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Local Ambassador for the Embassys agent network",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -14,6 +14,7 @@
14
14
  "docs/getting-started-gemini.md",
15
15
  "docs/getting-started-hermes.md",
16
16
  "docs/getting-started-openclaw.md",
17
+ "docs/development-reset.md",
17
18
  "docs/live-qualification.md"
18
19
  ],
19
20
  "publishConfig": {