@dynamicagents/core 0.9.0

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 (168) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +522 -0
  3. package/dist/a2a/agent-stub.d.ts +60 -0
  4. package/dist/a2a/agent-stub.js +1 -0
  5. package/dist/a2a/caller-token.d.ts +44 -0
  6. package/dist/a2a/caller-token.js +61 -0
  7. package/dist/a2a/caller.d.ts +23 -0
  8. package/dist/a2a/caller.js +33 -0
  9. package/dist/a2a/card.d.ts +158 -0
  10. package/dist/a2a/card.js +163 -0
  11. package/dist/a2a/context.d.ts +19 -0
  12. package/dist/a2a/context.js +61 -0
  13. package/dist/a2a/deliver.d.ts +159 -0
  14. package/dist/a2a/deliver.js +185 -0
  15. package/dist/a2a/executor.d.ts +84 -0
  16. package/dist/a2a/executor.js +106 -0
  17. package/dist/a2a/index.d.ts +35 -0
  18. package/dist/a2a/index.js +34 -0
  19. package/dist/a2a/notify.d.ts +106 -0
  20. package/dist/a2a/notify.js +180 -0
  21. package/dist/a2a/parts.d.ts +45 -0
  22. package/dist/a2a/parts.js +94 -0
  23. package/dist/a2a/push.d.ts +70 -0
  24. package/dist/a2a/push.js +53 -0
  25. package/dist/a2a/self-origin.d.ts +91 -0
  26. package/dist/a2a/self-origin.js +114 -0
  27. package/dist/a2a/task-store.d.ts +44 -0
  28. package/dist/a2a/task-store.js +99 -0
  29. package/dist/a2a/task.d.ts +85 -0
  30. package/dist/a2a/task.js +15 -0
  31. package/dist/a2a/verify.d.ts +80 -0
  32. package/dist/a2a/verify.js +143 -0
  33. package/dist/agent/budget.d.ts +46 -0
  34. package/dist/agent/budget.js +42 -0
  35. package/dist/agent/control.d.ts +109 -0
  36. package/dist/agent/control.js +115 -0
  37. package/dist/agent/errors.d.ts +85 -0
  38. package/dist/agent/errors.js +64 -0
  39. package/dist/agent/final-reply.d.ts +49 -0
  40. package/dist/agent/final-reply.js +68 -0
  41. package/dist/agent/history.d.ts +97 -0
  42. package/dist/agent/history.js +133 -0
  43. package/dist/agent/index.d.ts +29 -0
  44. package/dist/agent/index.js +29 -0
  45. package/dist/agent/inference.d.ts +110 -0
  46. package/dist/agent/inference.js +120 -0
  47. package/dist/agent/model.d.ts +90 -0
  48. package/dist/agent/model.js +1 -0
  49. package/dist/agent/session.d.ts +100 -0
  50. package/dist/agent/session.js +82 -0
  51. package/dist/agent/workers-ai/index.d.ts +23 -0
  52. package/dist/agent/workers-ai/index.js +23 -0
  53. package/dist/agent/workers-ai/runtime.d.ts +42 -0
  54. package/dist/agent/workers-ai/runtime.js +63 -0
  55. package/dist/alarm/index.d.ts +77 -0
  56. package/dist/alarm/index.js +116 -0
  57. package/dist/config.d.ts +202 -0
  58. package/dist/config.js +135 -0
  59. package/dist/contract/index.d.ts +9 -0
  60. package/dist/contract/index.js +8 -0
  61. package/dist/contract/plugin.d.ts +324 -0
  62. package/dist/contract/plugin.js +114 -0
  63. package/dist/contract/recipe.d.ts +180 -0
  64. package/dist/contract/recipe.js +1 -0
  65. package/dist/contract/validation.d.ts +91 -0
  66. package/dist/contract/validation.js +84 -0
  67. package/dist/db/db.d.ts +147 -0
  68. package/dist/db/db.js +90 -0
  69. package/dist/db/index.d.ts +8 -0
  70. package/dist/db/index.js +8 -0
  71. package/dist/db/migrations/index.d.ts +20 -0
  72. package/dist/db/migrations/index.js +60 -0
  73. package/dist/db/models/subtasks.d.ts +100 -0
  74. package/dist/db/models/subtasks.js +241 -0
  75. package/dist/db/models/tasks.d.ts +118 -0
  76. package/dist/db/models/tasks.js +274 -0
  77. package/dist/db/schema.d.ts +468 -0
  78. package/dist/db/schema.js +88 -0
  79. package/dist/env.d.ts +53 -0
  80. package/dist/env.js +47 -0
  81. package/dist/host/agent.d.ts +305 -0
  82. package/dist/host/agent.js +400 -0
  83. package/dist/host/index.d.ts +20 -0
  84. package/dist/host/index.js +19 -0
  85. package/dist/host/plugin-host.d.ts +42 -0
  86. package/dist/host/plugin-host.js +1 -0
  87. package/dist/index.d.ts +19 -0
  88. package/dist/index.js +17 -0
  89. package/dist/job/index.d.ts +21 -0
  90. package/dist/job/index.js +21 -0
  91. package/dist/job/lifecycle.d.ts +176 -0
  92. package/dist/job/lifecycle.js +230 -0
  93. package/dist/job/state.d.ts +92 -0
  94. package/dist/job/state.js +40 -0
  95. package/dist/platform.d.ts +138 -0
  96. package/dist/platform.js +140 -0
  97. package/dist/round/agent.d.ts +271 -0
  98. package/dist/round/agent.js +678 -0
  99. package/dist/round/index.d.ts +25 -0
  100. package/dist/round/index.js +23 -0
  101. package/dist/round/policy.d.ts +98 -0
  102. package/dist/round/policy.js +1 -0
  103. package/dist/round/subagent.d.ts +87 -0
  104. package/dist/round/subagent.js +108 -0
  105. package/dist/round/turn.d.ts +249 -0
  106. package/dist/round/turn.js +564 -0
  107. package/dist/round/workflow.d.ts +147 -0
  108. package/dist/round/workflow.js +387 -0
  109. package/dist/runtime/index.d.ts +127 -0
  110. package/dist/runtime/index.js +186 -0
  111. package/dist/runtime/tool-families.d.ts +32 -0
  112. package/dist/runtime/tool-families.js +61 -0
  113. package/dist/subagent/fingerprint.d.ts +37 -0
  114. package/dist/subagent/fingerprint.js +92 -0
  115. package/dist/subagent/index.d.ts +169 -0
  116. package/dist/subagent/index.js +330 -0
  117. package/dist/subagent/prompt.d.ts +32 -0
  118. package/dist/subagent/prompt.js +37 -0
  119. package/dist/subagent/run.d.ts +157 -0
  120. package/dist/subagent/run.js +540 -0
  121. package/dist/subagent/workspace.d.ts +85 -0
  122. package/dist/subagent/workspace.js +127 -0
  123. package/dist/subtasks/catalog.d.ts +40 -0
  124. package/dist/subtasks/catalog.js +36 -0
  125. package/dist/subtasks/decomposition.d.ts +85 -0
  126. package/dist/subtasks/decomposition.js +156 -0
  127. package/dist/subtasks/delegate.d.ts +120 -0
  128. package/dist/subtasks/delegate.js +131 -0
  129. package/dist/subtasks/index.d.ts +9 -0
  130. package/dist/subtasks/index.js +9 -0
  131. package/dist/subtasks/subtask-types.d.ts +91 -0
  132. package/dist/subtasks/subtask-types.js +103 -0
  133. package/dist/subtasks/types.d.ts +295 -0
  134. package/dist/subtasks/types.js +15 -0
  135. package/dist/testing/auth.d.ts +34 -0
  136. package/dist/testing/auth.js +35 -0
  137. package/dist/testing/do.d.ts +29 -0
  138. package/dist/testing/do.js +25 -0
  139. package/dist/testing/fake-session.d.ts +26 -0
  140. package/dist/testing/fake-session.js +37 -0
  141. package/dist/testing/fixtures.d.ts +64 -0
  142. package/dist/testing/fixtures.js +104 -0
  143. package/dist/testing/harness.d.ts +97 -0
  144. package/dist/testing/harness.js +138 -0
  145. package/dist/testing/index.d.ts +31 -0
  146. package/dist/testing/index.js +35 -0
  147. package/dist/testing/mock-model.d.ts +77 -0
  148. package/dist/testing/mock-model.js +136 -0
  149. package/dist/testing/node.d.ts +56 -0
  150. package/dist/testing/node.js +56 -0
  151. package/dist/testing/vcr-global-setup.d.ts +12 -0
  152. package/dist/testing/vcr-global-setup.js +15 -0
  153. package/dist/testing/vcr-shared.d.ts +38 -0
  154. package/dist/testing/vcr-shared.js +33 -0
  155. package/dist/testing/vcr-spec.d.ts +25 -0
  156. package/dist/testing/vcr-spec.js +124 -0
  157. package/dist/testing/vcr-store.d.ts +86 -0
  158. package/dist/testing/vcr-store.js +191 -0
  159. package/dist/testing/vcr.d.ts +117 -0
  160. package/dist/testing/vcr.js +275 -0
  161. package/dist/worker/define-agent.d.ts +123 -0
  162. package/dist/worker/define-agent.js +20 -0
  163. package/dist/worker/index.d.ts +218 -0
  164. package/dist/worker/index.js +369 -0
  165. package/eslint-rules/index.js +31 -0
  166. package/eslint-rules/no-deprecated-object-properties.js +81 -0
  167. package/package.json +178 -0
  168. package/scripts/generate-keys.mjs +48 -0
@@ -0,0 +1,123 @@
1
+ import type { AgentManifest } from "../a2a/card.js";
2
+ import type { GatekeeperIdentity } from "../a2a/verify.js";
3
+ import type { TaskAgent } from "../a2a/agent-stub.js";
4
+ import { type AcceptedTurn } from "../a2a/executor.js";
5
+ /**
6
+ * One agent's wiring, declared once.
7
+ *
8
+ * ## What this replaces
9
+ *
10
+ * Mounting an agent used to mean writing the same four things by hand and keeping
11
+ * them in agreement: a `getAgent(identity)` that guards `identity.key` and reads a
12
+ * Durable Object binding, a `startTurn` that derives an idempotent workflow id and
13
+ * swallows the already-exists race, an entry in the `tenants` map, and — in the
14
+ * agent's own Workflow entrypoint — a second reference to the same DO binding.
15
+ *
16
+ * Four copies of one fact, and only the first two were even adjacent. The wiring
17
+ * also type-checked when it was **wrong**: naming a sibling's workflow binding on
18
+ * a tenant compiles perfectly and fails at runtime, after auth, after the turn was
19
+ * accepted, as a task that simply never calls back.
20
+ *
21
+ * ```ts
22
+ * export const reactive = defineAgent({
23
+ * tenant: "reactive",
24
+ * manifest,
25
+ * agent: (env: Env) => env.ReactiveAgent,
26
+ * workflow: (env: Env) => env.HANDLE_TASK_WORKFLOW
27
+ * });
28
+ *
29
+ * // the Worker entry
30
+ * export default {
31
+ * fetch: createA2AWorker<Env>({ manifest: hostManifest, agents: [reactive] })
32
+ * };
33
+ *
34
+ * // the agent's Workflow entrypoint
35
+ * await runHandleTask(event.payload, step, {
36
+ * resolveAgent: (identity) => reactive.resolveAgent(this.env, identity),
37
+ * …
38
+ * });
39
+ * ```
40
+ *
41
+ * ## Why accessors rather than binding names
42
+ *
43
+ * `agent` and `workflow` are functions of `env`, not strings. A string would have
44
+ * to be checked against `keyof Env` and then widened back to a namespace, which
45
+ * loses the Durable Object's own class — so the Workflow could not see the very
46
+ * methods it exists to drive. An accessor infers both: the tenant is mounted and
47
+ * the Workflow is driven from one declaration, `env.RactiveAgent` is a compile
48
+ * error, and `resolveAgent` comes back typed as the agent itself.
49
+ *
50
+ * `env` stays a parameter throughout, for the reason `src/env.ts` gives: core
51
+ * never reaches for a consumer's ambient bindings, and on Workers `env` does not
52
+ * exist at module scope anyway.
53
+ */
54
+ /**
55
+ * What `createA2AWorker` needs in order to mount an agent. The Durable Object's
56
+ * own class is irrelevant to routing, so this shape forgets it —
57
+ * {@link AgentDefinition} keeps it for the agent's Workflow.
58
+ */
59
+ export interface MountedAgent<TEnv> {
60
+ /** The tenant id a caller addresses this agent with. */
61
+ tenant: string;
62
+ /** The transport-independent half of this agent's card. */
63
+ manifest: AgentManifest;
64
+ resolveAgent(env: TEnv, identity: GatekeeperIdentity): TaskAgent;
65
+ startTurn(env: TEnv, turn: AcceptedTurn): Promise<void>;
66
+ }
67
+ /**
68
+ * {@link AgentDefinition} deliberately does **not** declare `extends
69
+ * MountedAgent`, even though every one satisfies it.
70
+ *
71
+ * A generic `DurableObjectStub<TAgent>` cannot be proven assignable to
72
+ * {@link TaskAgent} while `TAgent` is unresolved: the RPC stub type widens an
73
+ * *optional* method (`listTasks?`) to `Promise<undefined> | (…) => …`, and
74
+ * forcing the comparison also trips TypeScript's instantiation-depth limit — the
75
+ * same wall that made `PlainTask` necessary. At a concrete call site, where
76
+ * `TAgent` is a real agent class, the assignment resolves normally. So the check
77
+ * happens where it can actually succeed: passing `agents: [reactive]` to
78
+ * `createA2AWorker`.
79
+ */
80
+ export interface DefineAgentOptions<TEnv, TAgent extends Rpc.DurableObjectBranded> {
81
+ /**
82
+ * The tenant id a caller addresses this agent with, and what a gatekeeper
83
+ * registers against. Renaming one is a re-registration, not a refactor.
84
+ */
85
+ tenant: string;
86
+ /** The transport-independent half of this agent's card. */
87
+ manifest: AgentManifest;
88
+ /**
89
+ * This agent's Durable Object namespace. One instance per verified caller —
90
+ * the tenant picks the agent, `identity.key` picks which instance of it.
91
+ */
92
+ agent: (env: TEnv) => DurableObjectNamespace<TAgent>;
93
+ /** The Workflow this agent's turns run on. */
94
+ workflow: (env: TEnv) => Workflow<AcceptedTurn>;
95
+ }
96
+ export interface AgentDefinition<TEnv, TAgent extends Rpc.DurableObjectBranded> {
97
+ /** The tenant id a caller addresses this agent with. */
98
+ tenant: string;
99
+ /** The transport-independent half of this agent's card. */
100
+ manifest: AgentManifest;
101
+ /**
102
+ * Resolve the per-caller agent DO stub, keyed by the verified `identity.key`.
103
+ *
104
+ * Typed as the agent's **own** class, so the Workflow that drives its round
105
+ * methods reaches them through the same declaration the tenant is mounted with
106
+ * — the two cannot address different Durable Objects.
107
+ *
108
+ * Refuses a caller with no key rather than falling back to a shared instance:
109
+ * that key is what makes one caller's tasks unreachable from another's, so a
110
+ * missing one is a routing failure, not a default.
111
+ */
112
+ resolveAgent(env: TEnv, identity: GatekeeperIdentity): DurableObjectStub<TAgent>;
113
+ /**
114
+ * Start this agent's durable turn, idempotently.
115
+ *
116
+ * The instance id is derived from the gatekeeper's `messageId`, which is stable
117
+ * across dispatch retries — so a retry finding its instance already running is
118
+ * the idempotency working, not a failure. {@link ignoreAlreadyExists} swallows
119
+ * exactly that race and rethrows everything else.
120
+ */
121
+ startTurn(env: TEnv, turn: AcceptedTurn): Promise<void>;
122
+ }
123
+ export declare function defineAgent<TEnv, TAgent extends Rpc.DurableObjectBranded>(options: DefineAgentOptions<TEnv, TAgent>): AgentDefinition<TEnv, TAgent>;
@@ -0,0 +1,20 @@
1
+ import { ignoreAlreadyExists, workflowIdForMessage } from "../a2a/executor.js";
2
+ export function defineAgent(options) {
3
+ return {
4
+ tenant: options.tenant,
5
+ manifest: options.manifest,
6
+ resolveAgent(env, identity) {
7
+ if (!identity.key) {
8
+ throw new Error("identity.key is required to route to the agent DO");
9
+ }
10
+ const ns = options.agent(env);
11
+ return ns.get(ns.idFromName(identity.key));
12
+ },
13
+ startTurn(env, turn) {
14
+ return ignoreAlreadyExists(() => options.workflow(env).create({
15
+ id: workflowIdForMessage(turn.messageId),
16
+ params: { ...turn }
17
+ }));
18
+ }
19
+ };
20
+ }
@@ -0,0 +1,218 @@
1
+ import { type AgentManifest } from "../a2a/card.js";
2
+ import { type TurnStarter } from "../a2a/executor.js";
3
+ import type { AgentResolver } from "../a2a/agent-stub.js";
4
+ import { type A2ASecretsEnv } from "../env.js";
5
+ import type { MountedAgent } from "./define-agent.js";
6
+ /**
7
+ * The A2A Worker: the zero-trust, no-shared-secrets edge every Dynamic Agents agent
8
+ * puts in front of its Durable Object.
9
+ *
10
+ * Trust flows entirely on domains and asymmetric (Ed25519) signatures over
11
+ * public JWKS: a gatekeeper verifies and pins this agent's identity from its signed
12
+ * card at registration ("G knows R"), and this Worker verifies the gatekeeper's
13
+ * identity JWT on every JSON-RPC call ("R knows G"). No secret is ever shared in
14
+ * either direction.
15
+ *
16
+ * **Several agents share one Worker, addressed by `tenant`.** They share one
17
+ * origin, one endpoint, one signing key and one card at the well-known path;
18
+ * what differs is the tenant id on every request. That is the A2A mechanism for
19
+ * exactly this — `AgentInterface.tenant` is "an opaque string used for routing
20
+ * requests to a specific agent or tenant when multiple agents are served behind
21
+ * a single A2A endpoint", and §8.3.2 requires a client to send the value the
22
+ * selected interface declared.
23
+ *
24
+ * A tenant is **required on every request**. There is no default and no
25
+ * implicit routing: an absent tenant is an error, because guessing one would
26
+ * mean picking an agent the caller never named.
27
+ *
28
+ * This replaces mounting a handler per path prefix. That could not work: the
29
+ * card is a **well-known URI**, which RFC 8615 defines per-authority, so only
30
+ * one card per origin is discoverable at the registered path — a gatekeeper
31
+ * resolving `…/.well-known/agent-card.json` against the origin found whichever
32
+ * agent owned the bare path and pinned *its* key for all of them.
33
+ *
34
+ * Three routes:
35
+ *
36
+ * 1. `GET jwksPath` — the card-signing public JWKS, resolving every card's
37
+ * `jku`.
38
+ * 2. `GET …/.well-known/agent-card.json` — the signed **stub** card for the
39
+ * origin. Matched by suffix, since that path is fixed by the spec.
40
+ * 3. `POST rpcPath` — gatekeeper-authenticated JSON-RPC, routed to the named
41
+ * tenant. `GetExtendedAgentCard` returns that tenant's own signed card;
42
+ * everything else runs a turn against its Durable Object.
43
+ *
44
+ * Two independent checks keep one tenant's traffic out of another's:
45
+ * `audience` proves the token was minted for this deployment, and
46
+ * {@link file://../a2a/verify.ts TENANT_CLAIM} proves it was minted for *this
47
+ * agent on it*. The second is what makes `tenant` more than an unauthenticated
48
+ * routing hint in the request body.
49
+ */
50
+ export { defineAgent, type AgentDefinition, type DefineAgentOptions, type MountedAgent } from "./define-agent.js";
51
+ /**
52
+ * Default path serving the card-signing public JWKS (the card's `jku`).
53
+ *
54
+ * From `@dynamicagents/g2a-protocol`, because the gatekeeper serves its own JWKS at
55
+ * the same path and fetches ours from whatever `jku` says — see
56
+ * {@link file://../a2a/verify.ts} for why the two sides share a package rather
57
+ * than a comment. Re-exported so this stays importable from
58
+ * `@dynamicagents/core/worker`, where it has always lived.
59
+ */
60
+ export { JWKS_PATH } from "@dynamicagents/g2a-protocol";
61
+ /** The two secrets a mount signs and verifies with, already read off `env`. */
62
+ export interface A2ASecrets {
63
+ /** Ed25519 private JWK, as JSON. See {@link A2ASecretsEnv.A2A_SIGNING_KEY}. */
64
+ signingKey: string;
65
+ /** Origin allowlist. See {@link A2ASecretsEnv.GATEKEEPER_ORIGINS}. */
66
+ gatekeeperOrigins: string;
67
+ }
68
+ /** One agent served on this origin — everything that differs between tenants. */
69
+ export interface TenantAgent {
70
+ /** The transport-independent half of this agent's card. */
71
+ manifest: AgentManifest;
72
+ /** Resolve the agent DO stub for a verified caller. */
73
+ resolveAgent: AgentResolver;
74
+ /** Start the durable turn. Must be idempotent — see {@link TurnStarter}. */
75
+ startTurn: TurnStarter;
76
+ }
77
+ export interface A2AWorkerOptions<TEnv = A2ASecretsEnv> {
78
+ /**
79
+ * The **stub** card served at the well-known path.
80
+ *
81
+ * It describes the origin, not an agent. Every agent here is a tenant and its
82
+ * card is reached through `GetExtendedAgentCard`, so this card exists to be
83
+ * the one conformant, signed AgentCard at the URI RFC 8615 and the A2A IANA
84
+ * registration reserve — advertising the endpoint, the protocol binding and
85
+ * `extendedAgentCard`.
86
+ *
87
+ * It cannot enumerate the tenants: a card carries one interface entry and
88
+ * spec §8.3.2 has clients take the first, so listing siblings there would
89
+ * just make every client address the same one. Put their names in
90
+ * `description` for a human, and register them out of band.
91
+ */
92
+ manifest: AgentManifest;
93
+ /**
94
+ * The agents on this origin, keyed by tenant id.
95
+ *
96
+ * The id is opaque to the protocol — "an opaque string used for routing
97
+ * requests to a specific agent or tenant when multiple agents are served
98
+ * behind a single A2A endpoint". A caller names one on every request and this
99
+ * Worker refuses a request that does not.
100
+ *
101
+ * The tenant chooses *which agent*; the verified `identity.key` still chooses
102
+ * *which instance of it*, so two callers of one tenant stay in separate
103
+ * Durable Objects exactly as before.
104
+ *
105
+ * The escape hatch, and still fully supported: use it for an agent whose
106
+ * routing or turn-start is genuinely its own. {@link A2AWorkerOptions.agents}
107
+ * is the shorter form for the ordinary case. Supply at least one of the two.
108
+ */
109
+ tenants?: Record<string, TenantAgent>;
110
+ /**
111
+ * The agents on this origin, each declared once with
112
+ * {@link file://./define-agent.ts defineAgent}.
113
+ *
114
+ * Prefer this to {@link A2AWorkerOptions.tenants}: one declaration produces the
115
+ * tenant entry here *and* the resolver the agent's Workflow entrypoint uses, so
116
+ * the two cannot drift, and the binding names are type-constrained to bindings
117
+ * of the right kind. Merged over `tenants`, which is checked for duplicate
118
+ * tenant ids rather than silently overriding.
119
+ */
120
+ agents?: readonly MountedAgent<TEnv>[];
121
+ /** Path serving the public JWKS. Defaults to {@link JWKS_PATH}. */
122
+ jwksPath?: string;
123
+ /** Path this agent answers JSON-RPC on. Defaults to `/a2a`. */
124
+ rpcPath?: string;
125
+ /**
126
+ * Where to read this deployment's two secrets. Defaults to the documented
127
+ * names, `env.A2A_SIGNING_KEY` and `env.GATEKEEPER_ORIGINS`.
128
+ *
129
+ * There is **one signing key per origin**, not one per tenant: the card is
130
+ * per-origin now, so the key the gatekeeper pins is too. Nothing was lost — the
131
+ * tenants share a Worker and an `env`, so they could always read each other's
132
+ * secrets, and separate keys never expressed a boundary that existed.
133
+ *
134
+ * ```ts
135
+ * secrets: (env) => ({
136
+ * signingKey: env.AGENT_KEY,
137
+ * gatekeeperOrigins: env.ALLOWED_GATEKEEPERS
138
+ * })
139
+ * ```
140
+ *
141
+ * Renaming does not weaken anything: the same key is still Ed25519, still
142
+ * signs the cards and every callback JWT, and its public half is still what
143
+ * the gatekeeper pins. Only where it is read from changes.
144
+ */
145
+ secrets?: (env: TEnv) => A2ASecrets;
146
+ /**
147
+ * The audience a gatekeeper JWT must carry.
148
+ *
149
+ * Defaults to this deployment's **own endpoint** — `${origin}${rpcPath}`, the
150
+ * same URL its cards advertise as their interface — and that default is
151
+ * almost certainly what you want. Setting this is for a gatekeeper that mints
152
+ * something else.
153
+ *
154
+ * The audience is one half of a two-sided contract: whatever is required here
155
+ * has to be exactly what the calling gatekeeper *mints*, and a mismatch is a 401
156
+ * on every request. slack-gatekeeper mints
157
+ * `new URL(agent.a2aEndpoint).origin + pathname`, which is what this default
158
+ * matches.
159
+ *
160
+ * It proves the token was minted for **this deployment**, and deliberately
161
+ * says nothing about which agent on it — every tenant shares one endpoint and
162
+ * therefore one audience. {@link file://../a2a/verify.ts TENANT_CLAIM} is what
163
+ * separates them, and is the check to look at when reasoning about one agent
164
+ * spending another's token.
165
+ */
166
+ audience?: string | ((url: URL) => string);
167
+ /**
168
+ * Advertise `securitySchemes` on the card. **Defaults to `false`** — see
169
+ * `BuildCardOptions.advertiseSecuritySchemes` for why, and read that note
170
+ * before turning it on.
171
+ */
172
+ advertiseSecuritySchemes?: boolean;
173
+ /** Claim carrying the caller identity. Defaults to the Dynamic Agents namespace. */
174
+ identityClaim?: string;
175
+ /**
176
+ * Claim carrying the authorized tenant. Defaults to the Dynamic Agents namespace.
177
+ *
178
+ * Both claim names are one side of the same contract as `audience`: whatever
179
+ * is named here has to be exactly what the calling gatekeeper *mints*. Override
180
+ * them together, or not at all — a deployment fronted by something other than
181
+ * slack-gatekeeper that renames only the identity claim keeps reading the
182
+ * tenant from a key its gatekeeper never sets, and every request 401s on the
183
+ * empty-tenant comparison below.
184
+ */
185
+ tenantClaim?: string;
186
+ /**
187
+ * Require a `taskPushNotificationConfig` on every `SendMessage`.
188
+ *
189
+ * Defaults to `true`, which is the accept-and-notify contract: the agent
190
+ * accepts synchronously and delivers out of band, so a send with nowhere to
191
+ * call back is a request that can never be answered. Set `false` only for an
192
+ * agent that replies inline.
193
+ */
194
+ requirePushConfig?: boolean;
195
+ }
196
+ /**
197
+ * Build the Worker `fetch` handler.
198
+ *
199
+ * ```ts
200
+ * const handler = createA2AWorker({
201
+ * manifest: hostManifest,
202
+ * tenants: {
203
+ * reactive: { manifest, resolveAgent: getAgent, startTurn }
204
+ * }
205
+ * });
206
+ * export default { fetch: handler } satisfies ExportedHandler<Env>;
207
+ * ```
208
+ *
209
+ * Two overloads, because `secrets` is optional for exactly one shape of `env`.
210
+ * An `env` carrying the two documented names needs no reader; anything else has
211
+ * to say where its keys live, and the type system is where that gets enforced —
212
+ * the alternative is a `parsePrivateJwk` failure on the first request, which is
213
+ * both later and much harder to read.
214
+ */
215
+ export declare function createA2AWorker<TEnv extends A2ASecretsEnv>(options: A2AWorkerOptions<TEnv>): (request: Request, env: TEnv) => Promise<Response>;
216
+ export declare function createA2AWorker<TEnv extends object>(options: A2AWorkerOptions<TEnv> & {
217
+ secrets: (env: TEnv) => A2ASecrets;
218
+ }): (request: Request, env: TEnv) => Promise<Response>;