@embassys/ambassador 0.0.0 → 0.2.6
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.
- package/LICENSE +21 -0
- package/README.md +68 -2
- package/dist/agent-capabilities.d.ts +35 -0
- package/dist/agent-capabilities.js +221 -0
- package/dist/agent-capabilities.js.map +1 -0
- package/dist/ambassador-options.d.ts +9 -0
- package/dist/ambassador-options.js +31 -0
- package/dist/ambassador-options.js.map +1 -0
- package/dist/central-credential.d.ts +41 -0
- package/dist/central-credential.js +355 -0
- package/dist/central-credential.js.map +1 -0
- package/dist/central-enrollment.d.ts +31 -0
- package/dist/central-enrollment.js +278 -0
- package/dist/central-enrollment.js.map +1 -0
- package/dist/central-json.d.ts +8 -0
- package/dist/central-json.js +259 -0
- package/dist/central-json.js.map +1 -0
- package/dist/central-protected-transport.d.ts +21 -0
- package/dist/central-protected-transport.js +217 -0
- package/dist/central-protected-transport.js.map +1 -0
- package/dist/central-rest.d.ts +50 -0
- package/dist/central-rest.js +401 -0
- package/dist/central-rest.js.map +1 -0
- package/dist/cli.d.ts +26 -0
- package/dist/cli.js +131 -0
- package/dist/cli.js.map +1 -0
- package/dist/credential-store.d.ts +18 -0
- package/dist/credential-store.js +517 -0
- package/dist/credential-store.js.map +1 -0
- package/dist/delivery-profile.d.ts +43 -0
- package/dist/delivery-profile.js +253 -0
- package/dist/delivery-profile.js.map +1 -0
- package/dist/direct-delivery.d.ts +38 -0
- package/dist/direct-delivery.js +315 -0
- package/dist/direct-delivery.js.map +1 -0
- package/dist/dpop.d.ts +28 -0
- package/dist/dpop.js +119 -0
- package/dist/dpop.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/gateway-application.d.ts +32 -0
- package/dist/gateway-application.js +256 -0
- package/dist/gateway-application.js.map +1 -0
- package/dist/gateway-paths.d.ts +10 -0
- package/dist/gateway-paths.js +28 -0
- package/dist/gateway-paths.js.map +1 -0
- package/dist/guided-registration.d.ts +23 -0
- package/dist/guided-registration.js +117 -0
- package/dist/guided-registration.js.map +1 -0
- package/dist/identity.d.ts +20 -0
- package/dist/identity.js +54 -0
- package/dist/identity.js.map +1 -0
- package/dist/local-mcp.d.ts +28 -0
- package/dist/local-mcp.js +420 -0
- package/dist/local-mcp.js.map +1 -0
- package/dist/local-tool-result.d.ts +4 -0
- package/dist/local-tool-result.js +17 -0
- package/dist/local-tool-result.js.map +1 -0
- package/dist/mcp-contract.d.ts +10 -0
- package/dist/mcp-contract.js +63 -0
- package/dist/mcp-contract.js.map +1 -0
- package/dist/notification-journal.d.ts +24 -0
- package/dist/notification-journal.js +194 -0
- package/dist/notification-journal.js.map +1 -0
- package/dist/notification-relay.d.ts +31 -0
- package/dist/notification-relay.js +203 -0
- package/dist/notification-relay.js.map +1 -0
- package/dist/process-lock.d.ts +8 -0
- package/dist/process-lock.js +122 -0
- package/dist/process-lock.js.map +1 -0
- package/dist/sqlite-artifact.d.ts +7 -0
- package/dist/sqlite-artifact.js +121 -0
- package/dist/sqlite-artifact.js.map +1 -0
- package/dist/webhook-delivery.d.ts +23 -0
- package/dist/webhook-delivery.js +122 -0
- package/dist/webhook-delivery.js.map +1 -0
- package/docs/getting-started-claude.md +94 -0
- package/docs/getting-started-codex.md +103 -0
- package/docs/getting-started-gemini.md +87 -0
- package/docs/getting-started-hermes.md +84 -0
- package/docs/getting-started-openclaw.md +83 -0
- package/docs/live-qualification.md +174 -0
- package/package.json +48 -7
- package/index.js +0 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Get started with Gemini CLI
|
|
2
|
+
|
|
3
|
+
Release target: `@embassys/ambassador@0.2.6`. The profile is source-reviewed
|
|
4
|
+
against Gemini CLI 0.58.0, and its exact ACP initialization contract passed.
|
|
5
|
+
Real-agent direct and webhook qualification remain open under the one-release
|
|
6
|
+
qualification exception in ADR 0015.
|
|
7
|
+
|
|
8
|
+
Ambassador enables Gemini CLI only for this exact contract:
|
|
9
|
+
|
|
10
|
+
| Field | Value |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| MCP `clientInfo` | `gemini-cli-mcp-client` / `0.58.0` |
|
|
13
|
+
| Delivery modes | direct and webhook |
|
|
14
|
+
| Direct command | `gemini --acp` |
|
|
15
|
+
| Accepted ACP `agentInfo` | `gemini-cli` / `0.58.0` |
|
|
16
|
+
| Ambassador MCP in the direct session | ACP HTTP MCP injection |
|
|
17
|
+
|
|
18
|
+
Gemini CLI supplies native ACP, so Ambassador does not select or contain an
|
|
19
|
+
adapter. The reviewed release is
|
|
20
|
+
[`v0.58.0`](https://github.com/google-gemini/gemini-cli/tree/v0.58.0). Its
|
|
21
|
+
[`ACP mode documentation`](https://github.com/google-gemini/gemini-cli/blob/v0.58.0/docs/cli/acp-mode.md)
|
|
22
|
+
defines `gemini --acp`. Its
|
|
23
|
+
[`acpRpcDispatcher.ts`](https://github.com/google-gemini/gemini-cli/blob/v0.58.0/packages/cli/src/acp/acpRpcDispatcher.ts)
|
|
24
|
+
returns the `gemini-cli` ACP identity, and
|
|
25
|
+
[`acpSessionManager.ts`](https://github.com/google-gemini/gemini-cli/blob/v0.58.0/packages/cli/src/acp/acpSessionManager.ts)
|
|
26
|
+
maps session MCP configuration into Gemini CLI. The MCP client identity comes
|
|
27
|
+
from
|
|
28
|
+
[`mcp-client.ts`](https://github.com/google-gemini/gemini-cli/blob/v0.58.0/packages/core/src/tools/mcp-client.ts).
|
|
29
|
+
Other versions fail closed until the registry is reviewed and updated.
|
|
30
|
+
|
|
31
|
+
## Setup
|
|
32
|
+
|
|
33
|
+
1. Install Node.js `>=24.19.0 <25`, then install and authenticate Gemini CLI
|
|
34
|
+
0.58.0 using its normal setup. Ambassador never installs or updates Gemini.
|
|
35
|
+
2. For noninteractive provider authentication, set the appropriate approved
|
|
36
|
+
Gemini or Vertex variables outside chat. The profile accepts
|
|
37
|
+
`GEMINI_API_KEY`, `GOOGLE_API_KEY`, `GOOGLE_CLOUD_PROJECT`,
|
|
38
|
+
`GOOGLE_CLOUD_LOCATION`, and `GOOGLE_GENAI_USE_VERTEXAI`.
|
|
39
|
+
3. Generate the local MCP token without putting its value in chat or a command
|
|
40
|
+
argument:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
export AMBASSADOR_LOCAL_TOKEN="$(
|
|
44
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
|
|
45
|
+
)"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
4. If you may choose webhook delivery, create its secret in the same shell
|
|
49
|
+
before starting Ambassador:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
export AMBASSADOR_WEBHOOK_SECRET="$(
|
|
53
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
|
|
54
|
+
)"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
5. From the directory the direct agent may access, start the exact release and
|
|
58
|
+
keep it running in the foreground:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
npx --yes @embassys/ambassador@0.2.6 start \
|
|
62
|
+
--local-token-env=AMBASSADOR_LOCAL_TOKEN
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
6. Configure Gemini CLI's MCP client to use the loopback endpoint printed by
|
|
66
|
+
Ambassador, with a bearer token read from `AMBASSADOR_LOCAL_TOKEN`. Use the
|
|
67
|
+
provider's normal MCP configuration mechanism; do not copy the token value
|
|
68
|
+
into chat.
|
|
69
|
+
7. Ask Gemini CLI to register with your email and optional display name. The
|
|
70
|
+
first `register_agent` call contains `email` and, if wanted, `display_name`.
|
|
71
|
+
Ambassador recognizes the Gemini CLI profile and asks direct versus webhook,
|
|
72
|
+
with direct as the default.
|
|
73
|
+
8. For direct mode, choose direct. The follow-up repeats the same `email` and
|
|
74
|
+
optional `display_name` and adds `delivery: {"mode":"direct"}`. Ambassador
|
|
75
|
+
starts `gemini --acp` and injects its authenticated HTTP MCP server into the
|
|
76
|
+
new ACP session.
|
|
77
|
+
9. For webhook mode, choose webhook and provide the HTTPS receiver URL plus
|
|
78
|
+
the environment-variable name `AMBASSADOR_WEBHOOK_SECRET`. The follow-up
|
|
79
|
+
repeats the registration fields and adds `delivery.mode`, `delivery.url`,
|
|
80
|
+
and `delivery.secret_env`; it never sends the secret value.
|
|
81
|
+
10. Enter the email verification code when Gemini CLI asks for it. Gemini CLI
|
|
82
|
+
calls `verify_email` with that `email` and six-digit `code`; the central
|
|
83
|
+
token and DPoP key stay inside Ambassador.
|
|
84
|
+
|
|
85
|
+
Gemini owns provider authentication and history. Ambassador never receives the
|
|
86
|
+
provider credentials, central token, or DPoP private key. Never put the local
|
|
87
|
+
token or a provider credential in chat or registration arguments.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Get started with Hermes Agent
|
|
2
|
+
|
|
3
|
+
Release target: `@embassys/ambassador@0.2.6`. The profile is source-reviewed
|
|
4
|
+
against Hermes Agent 0.21.0. Real-agent direct and webhook qualification remain
|
|
5
|
+
open under the one-release qualification exception in ADR 0015.
|
|
6
|
+
|
|
7
|
+
Ambassador enables Hermes only for this exact contract:
|
|
8
|
+
|
|
9
|
+
| Field | Value |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| MCP `clientInfo` | `mcp` / `0.1.0` |
|
|
12
|
+
| Delivery modes | direct and webhook |
|
|
13
|
+
| Direct command | `hermes-acp` |
|
|
14
|
+
| Accepted ACP `agentInfo` | `hermes-agent` / `0.21.0` |
|
|
15
|
+
| Ambassador MCP in the direct session | ACP HTTP MCP injection |
|
|
16
|
+
|
|
17
|
+
The contract was reviewed at Hermes revision
|
|
18
|
+
`1cb3ab617363ffab9e55239a7d2ab0d6f9c10473`. Hermes pins Python MCP 2.0.0 and
|
|
19
|
+
constructs `ClientSession` without overriding its client identity in
|
|
20
|
+
[`mcp_tool.py`](https://github.com/NousResearch/hermes-agent/blob/1cb3ab617363ffab9e55239a7d2ab0d6f9c10473/tools/mcp_tool.py).
|
|
21
|
+
That SDK's exact `mcp` / `0.1.0` identity is defined by Python MCP 2.0.0's
|
|
22
|
+
[`DEFAULT_CLIENT_INFO`](https://github.com/modelcontextprotocol/python-sdk/blob/6f69a3758ebf2ee55ce050f58b470ce11af71133/src/mcp/client/session.py).
|
|
23
|
+
Hermes declares the `hermes-acp` entry point in
|
|
24
|
+
[`pyproject.toml`](https://github.com/NousResearch/hermes-agent/blob/1cb3ab617363ffab9e55239a7d2ab0d6f9c10473/pyproject.toml)
|
|
25
|
+
and returns its ACP identity in
|
|
26
|
+
[`acp_adapter/server.py`](https://github.com/NousResearch/hermes-agent/blob/1cb3ab617363ffab9e55239a7d2ab0d6f9c10473/acp_adapter/server.py).
|
|
27
|
+
Later versions fail closed until the registry is reviewed and updated.
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
1. Install Node.js `>=24.19.0 <25`, then install and authenticate Hermes Agent
|
|
32
|
+
0.21.0 using its normal provider setup. Ambassador never installs or updates
|
|
33
|
+
Hermes.
|
|
34
|
+
2. Generate the local MCP token without putting its value in chat or a command
|
|
35
|
+
argument:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
export AMBASSADOR_LOCAL_TOKEN="$(
|
|
39
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
|
|
40
|
+
)"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. If you may choose webhook delivery, create its secret in the same shell
|
|
44
|
+
before starting Ambassador:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
export AMBASSADOR_WEBHOOK_SECRET="$(
|
|
48
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
|
|
49
|
+
)"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
4. From the directory the direct agent may access, start the exact release and
|
|
53
|
+
keep it running in the foreground:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
npx --yes @embassys/ambassador@0.2.6 start \
|
|
57
|
+
--local-token-env=AMBASSADOR_LOCAL_TOKEN
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
5. Configure Hermes to use the loopback MCP endpoint printed by Ambassador,
|
|
61
|
+
with a bearer token read from `AMBASSADOR_LOCAL_TOKEN`. Use Hermes's normal
|
|
62
|
+
MCP configuration mechanism; do not copy the token value into chat.
|
|
63
|
+
6. Ask Hermes to register with your email and optional display name. The first
|
|
64
|
+
`register_agent` call contains `email` and, if wanted, `display_name`.
|
|
65
|
+
Ambassador recognizes the Hermes profile and asks direct versus webhook,
|
|
66
|
+
with direct as the default.
|
|
67
|
+
7. For direct mode, choose direct. The follow-up repeats the same `email` and
|
|
68
|
+
optional `display_name` and adds `delivery: {"mode":"direct"}`. Ambassador
|
|
69
|
+
starts `hermes-acp` and injects its authenticated HTTP MCP server into the
|
|
70
|
+
gateway-owned ACP session.
|
|
71
|
+
8. For webhook mode, choose webhook and provide the HTTPS receiver URL plus
|
|
72
|
+
the environment-variable name `AMBASSADOR_WEBHOOK_SECRET`. The follow-up
|
|
73
|
+
repeats the registration fields and adds `delivery.mode`, `delivery.url`,
|
|
74
|
+
and `delivery.secret_env`; it never sends the secret value.
|
|
75
|
+
9. Enter the email verification code when Hermes asks for it. Hermes calls
|
|
76
|
+
`verify_email` with that `email` and six-digit `code`; the central token and
|
|
77
|
+
DPoP key stay inside Ambassador.
|
|
78
|
+
|
|
79
|
+
Hermes receives neither the central token nor the DPoP private key. Never put
|
|
80
|
+
the local token or webhook secret in chat or registration arguments.
|
|
81
|
+
|
|
82
|
+
The opt-in real-agent runner injects its qualification MCP endpoint into the
|
|
83
|
+
Hermes ACP session and verifies the exact reviewed `clientInfo` when Hermes
|
|
84
|
+
calls the bounded qualification tool.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Get started with OpenClaw
|
|
2
|
+
|
|
3
|
+
Release target: `@embassys/ambassador@0.2.6`. The profile is source-reviewed
|
|
4
|
+
against OpenClaw 2026.8.1. Real-agent direct and webhook qualification remain
|
|
5
|
+
open under the one-release qualification exception in ADR 0015.
|
|
6
|
+
|
|
7
|
+
Ambassador enables OpenClaw only for this exact contract:
|
|
8
|
+
|
|
9
|
+
| Field | Value |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| MCP `clientInfo` | `openclaw-bundle-mcp` / `0.0.0` |
|
|
12
|
+
| Delivery modes | direct and webhook |
|
|
13
|
+
| Direct command | `openclaw acp` |
|
|
14
|
+
| Accepted ACP `agentInfo` | `openclaw-acp` / `2026.8.1` |
|
|
15
|
+
| Ambassador MCP in the direct session | provider configuration required |
|
|
16
|
+
|
|
17
|
+
The contract was reviewed at OpenClaw revision
|
|
18
|
+
`a68a4e39684168cf83201cf48261be23174bad3d`. The source defines the MCP alias in
|
|
19
|
+
[`agent-bundle-mcp-runtime.ts`](https://github.com/openclaw/openclaw/blob/a68a4e39684168cf83201cf48261be23174bad3d/src/agents/agent-bundle-mcp-runtime.ts),
|
|
20
|
+
the ACP identity in
|
|
21
|
+
[`acp/types.ts`](https://github.com/openclaw/openclaw/blob/a68a4e39684168cf83201cf48261be23174bad3d/src/acp/types.ts),
|
|
22
|
+
and the command in
|
|
23
|
+
[`acp-cli.ts`](https://github.com/openclaw/openclaw/blob/a68a4e39684168cf83201cf48261be23174bad3d/src/cli/acp-cli.ts).
|
|
24
|
+
Later versions fail closed until the registry is reviewed and updated.
|
|
25
|
+
|
|
26
|
+
## Setup
|
|
27
|
+
|
|
28
|
+
1. Install Node.js `>=24.19.0 <25`, then install and authenticate OpenClaw
|
|
29
|
+
2026.8.1 using its normal provider setup. Ambassador never installs or
|
|
30
|
+
updates OpenClaw.
|
|
31
|
+
2. Generate the local MCP token without putting its value in chat or a command
|
|
32
|
+
argument:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
export AMBASSADOR_LOCAL_TOKEN="$(
|
|
36
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
|
|
37
|
+
)"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
3. If you may choose webhook delivery, create its secret in the same shell
|
|
41
|
+
before starting Ambassador:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
export AMBASSADOR_WEBHOOK_SECRET="$(
|
|
45
|
+
node -e "process.stdout.write(require('node:crypto').randomBytes(24).toString('hex'))"
|
|
46
|
+
)"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
4. From the directory the direct agent may access, start the exact release and
|
|
50
|
+
keep it running in the foreground:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
npx --yes @embassys/ambassador@0.2.6 start \
|
|
54
|
+
--local-token-env=AMBASSADOR_LOCAL_TOKEN
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
5. Configure OpenClaw's MCP client to use the loopback endpoint printed by
|
|
58
|
+
Ambassador, with a bearer token read from `AMBASSADOR_LOCAL_TOKEN`.
|
|
59
|
+
OpenClaw's ACP interface does not accept session MCP injection, so this
|
|
60
|
+
normal provider configuration is also required for direct delivery.
|
|
61
|
+
6. Ask OpenClaw to register with your email and optional display name. The
|
|
62
|
+
first `register_agent` call contains `email` and, if wanted, `display_name`.
|
|
63
|
+
Ambassador recognizes the OpenClaw profile and asks direct versus webhook,
|
|
64
|
+
with direct as the default.
|
|
65
|
+
7. For direct mode, choose direct. The follow-up repeats the same `email` and
|
|
66
|
+
optional `display_name` and adds `delivery: {"mode":"direct"}`. Ambassador
|
|
67
|
+
records the canonical startup directory and rejects a later start from a
|
|
68
|
+
different directory.
|
|
69
|
+
8. For webhook mode, choose webhook and provide the HTTPS receiver URL plus
|
|
70
|
+
the environment-variable name `AMBASSADOR_WEBHOOK_SECRET`. The follow-up
|
|
71
|
+
repeats the registration fields and adds `delivery.mode`, `delivery.url`,
|
|
72
|
+
and `delivery.secret_env`; it never sends the secret value. Receiver-side
|
|
73
|
+
conversion to an OpenClaw-native hook belongs outside Ambassador.
|
|
74
|
+
9. Enter the email verification code when OpenClaw asks for it. OpenClaw calls
|
|
75
|
+
`verify_email` with that `email` and six-digit `code`; the central token and
|
|
76
|
+
DPoP key stay inside Ambassador.
|
|
77
|
+
|
|
78
|
+
OpenClaw receives neither the central token nor the DPoP private key. Never put
|
|
79
|
+
the local token or webhook secret in chat or registration arguments.
|
|
80
|
+
|
|
81
|
+
For the opt-in real-agent suite, configure this same provider-side MCP entry at
|
|
82
|
+
`http://127.0.0.1:8787/mcp` using `AMBASSADOR_QUALIFICATION_LOCAL_TOKEN`; the
|
|
83
|
+
runner verifies that OpenClaw calls it with the exact reviewed `clientInfo`.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Live central qualification
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This runbook records the controlled test of Ambassador's REST and DPoP client
|
|
6
|
+
against `https://mcp.embassys.ai`. It does not test central MCP, API-version
|
|
7
|
+
fallbacks, migration, token reissue, leases, conversations, or invented
|
|
8
|
+
general reply operations. It does test the deployed, action-specific
|
|
9
|
+
`submit_action_result` contract.
|
|
10
|
+
|
|
11
|
+
The runner covers the current package name, guided registration, one
|
|
12
|
+
full-message webhook target, and one direct target. The default direct target
|
|
13
|
+
is the deterministic mock ACP agent. A separately confirmed mode uses the
|
|
14
|
+
fixed Codex profile and `codex-acp` 1.8.0 with an isolated Codex login.
|
|
15
|
+
|
|
16
|
+
## Safety
|
|
17
|
+
|
|
18
|
+
- Use disposable Mailosaur addresses and synthetic action data.
|
|
19
|
+
- Read Mailosaur credentials from approved local secret storage.
|
|
20
|
+
- Keep addresses, codes, tokens, keys, proofs, messages, and payloads out of
|
|
21
|
+
commands, files, logs, screenshots, and reports.
|
|
22
|
+
- Capture only route names, status, timing, digests, and safe pass/fail evidence.
|
|
23
|
+
- Delete captured mail and all temporary state in cleanup.
|
|
24
|
+
|
|
25
|
+
## Required live checks after the cutover
|
|
26
|
+
|
|
27
|
+
1. Pack and scan the exact candidate package.
|
|
28
|
+
2. Create two disposable identities through authenticated local MCP.
|
|
29
|
+
3. Use the exact enabled `clientInfo` aliases for one webhook profile and one
|
|
30
|
+
direct profile. Prove the dual-mode registration result advertises direct
|
|
31
|
+
as its default before choosing the required mode.
|
|
32
|
+
4. Receive and use both verification emails without persisting their codes.
|
|
33
|
+
5. Restart and prove encrypted credential and nonsecret profile loading.
|
|
34
|
+
6. Prove valid Bearer plus DPoP requests and the negative DPoP matrix.
|
|
35
|
+
7. Validate the live action catalog against the recorded fixture schemas.
|
|
36
|
+
8. Request and decide one synthetic `get_phone_number` permission.
|
|
37
|
+
9. Deliver the action request to the direct target.
|
|
38
|
+
10. Submit one correlated synthetic result from the target and deliver the
|
|
39
|
+
resulting `action_response` to the webhook requester.
|
|
40
|
+
11. Prove each local acceptance or completion precedes its central
|
|
41
|
+
acknowledgement.
|
|
42
|
+
12. Record the consuming-poll restart-loss and non-idempotent result-submission
|
|
43
|
+
limitations.
|
|
44
|
+
13. Stop all processes, delete mail and temporary state, and scan artifacts.
|
|
45
|
+
|
|
46
|
+
Use the mock webhook receiver and either the mock ACP agent or the fixed real
|
|
47
|
+
Codex mode for this live REST test. Real-agent qualification for all five
|
|
48
|
+
enabled profiles remains a separate local matrix in
|
|
49
|
+
[Delivery qualification](qualification.md).
|
|
50
|
+
|
|
51
|
+
The controlled runner must require an explicit confirmation phrase before any
|
|
52
|
+
live request. It must record the reviewed central source revision or note that
|
|
53
|
+
the deployment does not expose one.
|
|
54
|
+
|
|
55
|
+
After packing and clean-installing the candidate, set
|
|
56
|
+
`AMBASSADOR_PACKED_CLI`, `AMBASSADOR_PACKED_TARBALL`, and
|
|
57
|
+
`AMBASSADOR_CONFIRM_LIVE_QUALIFICATION` to the confirmation phrase embedded in
|
|
58
|
+
`scripts/live-qualification.mjs`, then run `pnpm run qualify:live`. In default
|
|
59
|
+
mode, the runner uses the mock ACP fixture compiled by `pnpm run test:build`
|
|
60
|
+
and does not run a paid provider.
|
|
61
|
+
|
|
62
|
+
For the real Codex mode, prepare an owner-only temporary home containing only
|
|
63
|
+
the copied Codex authentication needed for the run. Put exact
|
|
64
|
+
`codex-acp` 1.8.0 on `PATH`, then set:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
export AMBASSADOR_LIVE_DIRECT_AGENT=codex
|
|
68
|
+
export AMBASSADOR_CODEX_QUALIFICATION_HOME=/absolute/path/to/isolated/home
|
|
69
|
+
export AMBASSADOR_CONFIRM_LIVE_QUALIFICATION=run-live-qualification-with-real-codex-and-two-disposable-mailosaur-identities
|
|
70
|
+
pnpm run qualify:live
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The runner rejects an ordinary user home, checks the adapter version before it
|
|
74
|
+
contacts central, uses the compiled-in Codex command and profile, and never
|
|
75
|
+
accepts a command override. It also lets abandoned server-side polls expire
|
|
76
|
+
after the restart check before it enqueues a message. Delete the isolated home
|
|
77
|
+
after the run.
|
|
78
|
+
|
|
79
|
+
## Required report
|
|
80
|
+
|
|
81
|
+
Record only:
|
|
82
|
+
|
|
83
|
+
- date and reviewed server revision;
|
|
84
|
+
- live origin;
|
|
85
|
+
- packed Ambassador digest;
|
|
86
|
+
- qualification runner revision;
|
|
87
|
+
- status for each safe case;
|
|
88
|
+
- whether the target submitted a correlated action result and the requester
|
|
89
|
+
received it;
|
|
90
|
+
- returned action names and schema digests;
|
|
91
|
+
- whether a DPoP nonce was observed;
|
|
92
|
+
- delivery mode used for each synthetic message;
|
|
93
|
+
- artifact-scan result; and
|
|
94
|
+
- the known consuming-poll and result-submission limitations.
|
|
95
|
+
|
|
96
|
+
Do not include identities, IDs, codes, tokens, JWK coordinates, proof claims,
|
|
97
|
+
messages, action payloads, permission scopes, webhook details, prompts,
|
|
98
|
+
provider output, or remote error bodies.
|
|
99
|
+
|
|
100
|
+
## Correlated-result observation
|
|
101
|
+
|
|
102
|
+
At 00:43 BST on 2026-09-03, the real Codex mode passed against the live service
|
|
103
|
+
with `codex-acp` 1.8.0 and packed candidate
|
|
104
|
+
`7cbbf27fbd401024c51a48f6ae6b0a0b55059df200035cdbb33c72faf9ab4d70`.
|
|
105
|
+
The runner's UTC date field was still 2026-09-02. The reviewed central source
|
|
106
|
+
revision was `ac3f7a6e33829eb80301c7944f611d29cc2499b5`, the exact runner digest was
|
|
107
|
+
`769959d2bec4f7b436b9376570e940a14756c4f563e5f07343de9475c4cf3236`,
|
|
108
|
+
and the deployment did not expose its revision.
|
|
109
|
+
|
|
110
|
+
The run registered and verified two disposable Mailosaur identities. The mock
|
|
111
|
+
requester used webhook delivery; the target used direct ACP delivery to real
|
|
112
|
+
Codex. The requester asked for `get_phone_number`. Codex received the
|
|
113
|
+
`permission_request` through Ambassador's central poll and called
|
|
114
|
+
`respond_to_permission`. After central returned the grant to the requester's
|
|
115
|
+
webhook, the requester called `call_action`. Codex received the correlated
|
|
116
|
+
`action_call` and called `submit_action_result` exactly once with its `call_id`,
|
|
117
|
+
`success`, and the approved synthetic phone object. Central returned
|
|
118
|
+
`completed` and queued an `action_response` with the same call ID, action type,
|
|
119
|
+
status, and result. The requester received that response through its webhook,
|
|
120
|
+
and Ambassador acknowledged it.
|
|
121
|
+
|
|
122
|
+
The same run also passed encrypted restart, the DPoP positive case and missing,
|
|
123
|
+
wrong-key, stale, future, wrong-URL, wrong-method, wrong-token-hash, and replay
|
|
124
|
+
failures, the six-action live catalog and schema digests, acknowledgement order,
|
|
125
|
+
zero central MCP requests, artifact scanning, and mail and temporary-state
|
|
126
|
+
cleanup. The external isolated credential copy was removed after the run. No
|
|
127
|
+
defect appeared in the live `submit_action_result` path.
|
|
128
|
+
|
|
129
|
+
The pass used an owner-only `AGENTS.md` in the isolated Codex working directory
|
|
130
|
+
to represent the user's prior approval of only this synthetic permission and
|
|
131
|
+
result. It did not test a live interactive prompt to the user. An earlier run
|
|
132
|
+
without that local policy reached Codex, which called `respond_to_permission`,
|
|
133
|
+
but the permission was not granted; no action or result submission followed.
|
|
134
|
+
This is expected for a background ACP session with no interactive user.
|
|
135
|
+
|
|
136
|
+
A second attempt accepted the permission request but timed out before Codex
|
|
137
|
+
received it. The source and request sequence indicate that an abandoned
|
|
138
|
+
server-side long poll from the deliberate restart consumed the queued message
|
|
139
|
+
after its local HTTP request had been aborted. Central marks messages delivered
|
|
140
|
+
during polling and provides no lease or redelivery. The runner now waits 31
|
|
141
|
+
seconds after stopping the old gateways before it starts replacements; the
|
|
142
|
+
subsequent run passed. This is evidence of the existing restart-loss window,
|
|
143
|
+
not a failure of the result endpoint.
|
|
144
|
+
|
|
145
|
+
The live process used installed Node 24.14.0, below the package's declared
|
|
146
|
+
24.19.0 floor, because no in-range Node runtime was installed. Functional live
|
|
147
|
+
behavior passed. The supported-Node repeat remains part of the qualification
|
|
148
|
+
record even though the user approved 0.2.6 as a one-release exception before
|
|
149
|
+
that repeat.
|
|
150
|
+
|
|
151
|
+
## Earlier direct observation
|
|
152
|
+
|
|
153
|
+
On 2026-09-02, real Codex had already passed delivery, injected Ambassador MCP
|
|
154
|
+
use, and acknowledgement with candidate
|
|
155
|
+
`22a65d370897172a726b4890bade780e907c2c38ccf5d6cb5e347c9c01f14ec7`.
|
|
156
|
+
That run predated adoption of `submit_action_result` and is not evidence for the
|
|
157
|
+
correlated-result contract. Earlier mock-target delivery timeouts remained
|
|
158
|
+
unexplained at that point; the restart race above now explains one reproducible
|
|
159
|
+
class of such timeout.
|
|
160
|
+
|
|
161
|
+
## Baseline observation
|
|
162
|
+
|
|
163
|
+
On 2026-09-02, the packed pre-ADR-0038 implementation passed registration, Mailosaur
|
|
164
|
+
email receipt, verification, encrypted restart, the DPoP positive and negative
|
|
165
|
+
matrix, six-action catalog validation, permission request and decision,
|
|
166
|
+
permission-response delivery, one `get_email` delivery, consuming polls,
|
|
167
|
+
acknowledgements, and forbidden-marker scans.
|
|
168
|
+
|
|
169
|
+
It used no central MCP request and observed no initial nonce challenge. The
|
|
170
|
+
final `get_my_permissions` check matched the deployed email-field model.
|
|
171
|
+
Captured mail and temporary process state were deleted.
|
|
172
|
+
|
|
173
|
+
This observation remains useful evidence for ADR 0037 only. It is not release
|
|
174
|
+
evidence for the Ambassador delivery cutover.
|
package/package.json
CHANGED
|
@@ -1,15 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embassys/ambassador",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "Local Ambassador for the Embassys agent network",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"
|
|
7
|
-
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/embassys/ambassador.git"
|
|
9
|
+
},
|
|
8
10
|
"files": [
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
+
"dist",
|
|
12
|
+
"docs/getting-started-claude.md",
|
|
13
|
+
"docs/getting-started-codex.md",
|
|
14
|
+
"docs/getting-started-gemini.md",
|
|
15
|
+
"docs/getting-started-hermes.md",
|
|
16
|
+
"docs/getting-started-openclaw.md",
|
|
17
|
+
"docs/live-qualification.md"
|
|
11
18
|
],
|
|
12
19
|
"publishConfig": {
|
|
13
20
|
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
23
|
+
"bin": {
|
|
24
|
+
"ambassador": "dist/cli.js"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=24.19.0 <25"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@agentclientprotocol/sdk": "1.4.0",
|
|
31
|
+
"@modelcontextprotocol/client": "2.0.0",
|
|
32
|
+
"@modelcontextprotocol/node": "2.0.0",
|
|
33
|
+
"@modelcontextprotocol/server": "2.0.0",
|
|
34
|
+
"better-sqlite3": "13.0.3",
|
|
35
|
+
"zod": "4.4.3"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@biomejs/biome": "2.5.10",
|
|
39
|
+
"@types/better-sqlite3": "9.6.0",
|
|
40
|
+
"@types/node": "24.13.3",
|
|
41
|
+
"typescript": "7.0.2"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc -p tsconfig.build.json",
|
|
45
|
+
"check": "pnpm run lint && pnpm run typecheck && pnpm test",
|
|
46
|
+
"clean": "node scripts/clean.mjs",
|
|
47
|
+
"format": "biome check --write .",
|
|
48
|
+
"lint": "biome check .",
|
|
49
|
+
"qualify:agents": "node scripts/qualify-agents.mjs",
|
|
50
|
+
"qualify:live": "node scripts/live-qualification.mjs",
|
|
51
|
+
"test": "pnpm run test:build && node scripts/run-tests.mjs",
|
|
52
|
+
"test:build": "node scripts/clean.mjs .test-dist && tsc -p tsconfig.test.json",
|
|
53
|
+
"test:coverage": "pnpm run test:build && node scripts/run-tests.mjs --coverage",
|
|
54
|
+
"typecheck": "tsc -p tsconfig.test.json --noEmit"
|
|
14
55
|
}
|
|
15
|
-
}
|
|
56
|
+
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|