@ziggs-ai/agent-sdk 0.10.8 → 0.11.1

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 (104) hide show
  1. package/CHANGELOG.md +11 -11
  2. package/README.md +1 -1
  3. package/dist/AgentHost.d.ts +96 -16
  4. package/dist/AgentHost.js +205 -25
  5. package/dist/adapters/AnthropicAdapter.js +1 -1
  6. package/dist/adapters/McpAdapter.d.ts +10 -10
  7. package/dist/adapters/McpAdapter.js +31 -21
  8. package/dist/adapters/OpenAIAdapter.js +1 -1
  9. package/dist/agent/Agent.d.ts +2 -2
  10. package/dist/agent/ClaudeSdkAgent.d.ts +15 -6
  11. package/dist/agent/ClaudeSdkAgent.js +149 -48
  12. package/dist/agent/claudeCognition.d.ts +3 -3
  13. package/dist/agent/claudeCognition.js +7 -7
  14. package/dist/agent/claudeSdkTools.d.ts +3 -3
  15. package/dist/agent/claudeSdkTools.js +34 -15
  16. package/dist/agent/hostedAgentConnection.d.ts +1 -1
  17. package/dist/agent/hostedAgentConnection.js +1 -1
  18. package/dist/agent/toolManagerToSdkMcp.d.ts +1 -1
  19. package/dist/agent/toolManagerToSdkMcp.js +2 -2
  20. package/dist/context/applyEffects.js +1 -1
  21. package/dist/defineAgent.js +33 -4
  22. package/dist/formatters/HistoryFormatter.js +2 -2
  23. package/dist/index.d.ts +4 -2
  24. package/dist/index.js +8 -5
  25. package/dist/ingress/normalizeIncoming.d.ts +1 -1
  26. package/dist/ingress/normalizeIncoming.js +7 -7
  27. package/dist/pricing/fleetDefaults.d.ts +3 -3
  28. package/dist/pricing/fleetDefaults.js +3 -3
  29. package/dist/pricing/fleetEvalFree.d.ts +1 -1
  30. package/dist/pricing/fleetEvalFree.js +1 -1
  31. package/dist/pricing/fleetFreeTierA.gen.d.ts +1 -1
  32. package/dist/pricing/fleetFreeTierA.gen.js +1 -1
  33. package/dist/pricing/fleetTierByAgentId.gen.d.ts +2 -2
  34. package/dist/pricing/fleetTierByAgentId.gen.js +9 -2
  35. package/dist/runtime/AgentMachine.d.ts +1 -1
  36. package/dist/runtime/AgentMachine.js +8 -8
  37. package/dist/runtime/PromptBuilder.d.ts +2 -2
  38. package/dist/runtime/PromptBuilder.js +3 -3
  39. package/dist/runtime/bootstrapCtx.d.ts +1 -1
  40. package/dist/runtime/bootstrapCtx.js +2 -2
  41. package/dist/runtime/buildOutcome.d.ts +1 -1
  42. package/dist/runtime/buildOutcome.js +4 -4
  43. package/dist/runtime/defaults.d.ts +5 -5
  44. package/dist/runtime/defaults.js +4 -4
  45. package/dist/runtime/deliveryWriteKeys.d.ts +1 -1
  46. package/dist/runtime/deliveryWriteKeys.js +3 -3
  47. package/dist/runtime/kickoff.d.ts +3 -3
  48. package/dist/runtime/kickoff.js +3 -3
  49. package/dist/runtime/runMechanical.d.ts +1 -1
  50. package/dist/runtime/runMechanical.js +1 -1
  51. package/dist/runtime/runTurn.d.ts +1 -1
  52. package/dist/runtime/runTurn.js +10 -10
  53. package/dist/runtime/taskBookkeeping.d.ts +3 -3
  54. package/dist/runtime/taskBookkeeping.js +3 -3
  55. package/dist/runtime/taskIntake.js +2 -2
  56. package/dist/server/ConnectionPool.js +1 -1
  57. package/dist/server/EventQueue.d.ts +1 -1
  58. package/dist/server/EventQueue.js +1 -1
  59. package/dist/server/SeenMessages.d.ts +2 -2
  60. package/dist/server/SeenMessages.js +2 -2
  61. package/dist/server/ZiggsEffectHandler.d.ts +2 -2
  62. package/dist/server/ZiggsEffectHandler.js +18 -9
  63. package/dist/server/agreements/AgreementService.d.ts +3 -8
  64. package/dist/server/agreements/AgreementService.js +4 -7
  65. package/dist/server/inboxLoop.d.ts +5 -5
  66. package/dist/server/inboxLoop.js +27 -11
  67. package/dist/server/polls/PollRunner.d.ts +36 -1
  68. package/dist/server/polls/PollRunner.js +42 -2
  69. package/dist/server/questMatch.d.ts +1 -1
  70. package/dist/server/questMatch.js +1 -1
  71. package/dist/server/runLauncher.js +3 -3
  72. package/dist/server/tasks/TaskService.d.ts +5 -5
  73. package/dist/server/tools/index.d.ts +1 -0
  74. package/dist/server/tools/index.js +7 -6
  75. package/dist/server/tools/tier1/protocolRunner.d.ts +1 -1
  76. package/dist/server/tools/tier1/protocolRunner.js +19 -19
  77. package/dist/server/tools/tier1/protocolTools.js +4 -4
  78. package/dist/server/tools/tier2/artifactTools.js +2 -2
  79. package/dist/server/tools/tier2/chatTools.js +2 -2
  80. package/dist/server/tools/tier2/connectionTools.js +3 -3
  81. package/dist/server/tools/tier2/contextTools.js +1 -1
  82. package/dist/server/tools/tier2/discoveryTools.js +2 -2
  83. package/dist/server/tools/tier2/grantsTools.js +1 -1
  84. package/dist/server/tools/tier2/linkTools.js +3 -3
  85. package/dist/server/tools/tier2/marketplaceTools.js +1 -1
  86. package/dist/server/tools/tier2/mcpConnectionTools.d.ts +4 -0
  87. package/dist/server/tools/tier2/mcpConnectionTools.js +136 -0
  88. package/dist/server/tools/tier2/paymentTools.js +1 -1
  89. package/dist/shared/operatorKeyClaims.d.ts +2 -2
  90. package/dist/shared/operatorKeyClaims.js +1 -1
  91. package/dist/tasks/protocolRegistry.d.ts +1 -1
  92. package/dist/tasks/protocolRegistry.js +1 -1
  93. package/dist/tools/ToolManager.d.ts +1 -1
  94. package/dist/tools/ToolManager.js +3 -2
  95. package/dist/tools/capabilityAdapter.d.ts +1 -1
  96. package/dist/tools/capabilityAdapter.js +3 -3
  97. package/dist/tools/defineTool.d.ts +7 -0
  98. package/dist/tools/defineTool.js +13 -1
  99. package/dist/tools/needs.d.ts +54 -0
  100. package/dist/tools/needs.js +84 -0
  101. package/dist/tools/recordReport.d.ts +3 -3
  102. package/dist/tools/recordReport.js +3 -3
  103. package/dist/types.d.ts +28 -18
  104. package/package.json +3 -3
@@ -0,0 +1,54 @@
1
+ /**
2
+ * needs.ts — what an agent cannot work without, declared once.
3
+ *
4
+ * An agent is otherwise two hand-written lists — instructions and tools — with
5
+ * nothing checking they agree, so a prompt can promise work the toolset has no
6
+ * way to do and the mismatch only surfaces on a real hire. A third list to
7
+ * compare against the other two would drift the same way, so the declaration
8
+ * DERIVES the tools instead. The author never writes that part of the list, so
9
+ * the mismatch cannot be written.
10
+ *
11
+ * Scope is agents built on this SDK.
12
+ */
13
+ import { type ToolDefinition } from './defineTool.js';
14
+ /**
15
+ * A remote MCP server is stored as `provider: 'mcp'` and goes through the
16
+ * gateway. `connection_proxy` resolves a NAMED connector and refuses it with
17
+ * "Unknown provider: mcp" — the second wall linear-janitor hit.
18
+ */
19
+ export declare const MCP_PROVIDER = "mcp";
20
+ /**
21
+ * One shape for now, the one we have actually hit. A second kind means a case in
22
+ * {@link toolsForNeed}: a need nothing derives tools from is a need nothing
23
+ * enforces.
24
+ */
25
+ export interface ConnectionNeed {
26
+ /** Provider, e.g. 'mcp' or a named connector like 'github'. */
27
+ connection: string;
28
+ }
29
+ export type AgentNeed = ConnectionNeed;
30
+ /** Reads a manifest's `needs` field defensively — it crosses a package edge. */
31
+ export declare function normalizeNeeds(input: unknown): AgentNeed[];
32
+ /**
33
+ * The tools a stated need implies. `connection_list_grants` rides every need
34
+ * because seeing the grant is half of using it: the janitor's first failure was
35
+ * an agent that held a Linear grant and had no way to notice.
36
+ */
37
+ export declare function toolsForNeed(need: AgentNeed): ToolDefinition[];
38
+ /** Deduped by tool name, so overlapping needs (and a hand-listed tool) merge. */
39
+ export declare function toolsForNeeds(needs: AgentNeed[]): ToolDefinition[];
40
+ /** One line naming what is missing, for a refusal a human can act on. */
41
+ export declare function describeNeed(need: AgentNeed): string;
42
+ /**
43
+ * Which declared needs have no live grant behind them.
44
+ *
45
+ * `providers` are the providers of the agent's live connection grants. The label
46
+ * a grant carries is the provider, sometimes suffixed with the owner's account
47
+ * ("github — acme/infra"), so the provider is the part before the separator.
48
+ */
49
+ export declare function unmetNeeds(needs: AgentNeed[], providers: Array<string | null | undefined>): AgentNeed[];
50
+ /**
51
+ * The refusal itself. Names the missing access and who can fix it, because the
52
+ * agent cannot: issuing a connection grant is the connection owner's act.
53
+ */
54
+ export declare function unmetNeedsMessage(unmet: AgentNeed[]): string;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * needs.ts — what an agent cannot work without, declared once.
3
+ *
4
+ * An agent is otherwise two hand-written lists — instructions and tools — with
5
+ * nothing checking they agree, so a prompt can promise work the toolset has no
6
+ * way to do and the mismatch only surfaces on a real hire. A third list to
7
+ * compare against the other two would drift the same way, so the declaration
8
+ * DERIVES the tools instead. The author never writes that part of the list, so
9
+ * the mismatch cannot be written.
10
+ *
11
+ * Scope is agents built on this SDK.
12
+ */
13
+ import { toolName } from './defineTool.js';
14
+ import { connectionListGrantsTool, connectionProxyTool } from '../server/tools/tier2/connectionTools.js';
15
+ import { MCP_CONNECTION_TOOLS } from '../server/tools/tier2/mcpConnectionTools.js';
16
+ /**
17
+ * A remote MCP server is stored as `provider: 'mcp'` and goes through the
18
+ * gateway. `connection_proxy` resolves a NAMED connector and refuses it with
19
+ * "Unknown provider: mcp" — the second wall linear-janitor hit.
20
+ */
21
+ export const MCP_PROVIDER = 'mcp';
22
+ /** Reads a manifest's `needs` field defensively — it crosses a package edge. */
23
+ export function normalizeNeeds(input) {
24
+ if (!Array.isArray(input))
25
+ return [];
26
+ const out = [];
27
+ for (const raw of input) {
28
+ const connection = raw?.connection;
29
+ if (typeof connection === 'string' && connection.trim()) {
30
+ out.push({ connection: connection.trim() });
31
+ }
32
+ }
33
+ return out;
34
+ }
35
+ /**
36
+ * The tools a stated need implies. `connection_list_grants` rides every need
37
+ * because seeing the grant is half of using it: the janitor's first failure was
38
+ * an agent that held a Linear grant and had no way to notice.
39
+ */
40
+ export function toolsForNeed(need) {
41
+ return need.connection === MCP_PROVIDER
42
+ ? [connectionListGrantsTool, ...MCP_CONNECTION_TOOLS]
43
+ : [connectionListGrantsTool, connectionProxyTool];
44
+ }
45
+ /** Deduped by tool name, so overlapping needs (and a hand-listed tool) merge. */
46
+ export function toolsForNeeds(needs) {
47
+ const byName = new Map();
48
+ for (const need of needs) {
49
+ for (const tool of toolsForNeed(need)) {
50
+ const name = toolName(tool);
51
+ if (name)
52
+ byName.set(name, tool);
53
+ }
54
+ }
55
+ return [...byName.values()];
56
+ }
57
+ /** One line naming what is missing, for a refusal a human can act on. */
58
+ export function describeNeed(need) {
59
+ return need.connection === MCP_PROVIDER
60
+ ? 'a connection to an MCP server'
61
+ : `a ${need.connection} connection`;
62
+ }
63
+ /**
64
+ * Which declared needs have no live grant behind them.
65
+ *
66
+ * `providers` are the providers of the agent's live connection grants. The label
67
+ * a grant carries is the provider, sometimes suffixed with the owner's account
68
+ * ("github — acme/infra"), so the provider is the part before the separator.
69
+ */
70
+ export function unmetNeeds(needs, providers) {
71
+ const held = new Set(providers
72
+ .map((p) => String(p ?? '').split('—')[0].trim().toLowerCase())
73
+ .filter(Boolean));
74
+ return needs.filter((n) => !held.has(n.connection.toLowerCase()));
75
+ }
76
+ /**
77
+ * The refusal itself. Names the missing access and who can fix it, because the
78
+ * agent cannot: issuing a connection grant is the connection owner's act.
79
+ */
80
+ export function unmetNeedsMessage(unmet) {
81
+ const list = unmet.map(describeNeed).join(', ');
82
+ return (`Cannot start this task: no live grant for ${list}. ` +
83
+ 'Ask the connection owner to issue one for this agent, then re-assign the task.');
84
+ }
@@ -1,6 +1,6 @@
1
1
  import { type Creds } from '@ziggs-ai/api-client';
2
2
  /**
3
- * The canonical report shape (B1 convention — ZIG-561).
3
+ * The canonical report shape (B1 convention).
4
4
  * Matches Task.result as set by ziggs_task_set_result.
5
5
  */
6
6
  export interface TaskReport {
@@ -13,7 +13,7 @@ export interface RecordReportInput {
13
13
  taskId: string;
14
14
  report: TaskReport;
15
15
  /**
16
- * Optional container for the deliverable artifact (ZIG-1037 — it used to be
16
+ * Optional container for the deliverable artifact (it used to be
17
17
  * required). The task binding is what makes the deliverable retrievable and
18
18
  * readable by the task's parties; a chat or agreement only widens where it also
19
19
  * shows up. Pass at most one; when both arrive, agreementId wins.
@@ -32,7 +32,7 @@ export interface RecordReportResult {
32
32
  artifactId?: string;
33
33
  }
34
34
  /**
35
- * Record a conformant report for a completed task (B2 — ZIG-562).
35
+ * Record a conformant report for a completed task (B2).
36
36
  *
37
37
  * Always sets Task.result via updateTaskState (the canonical done payload).
38
38
  * When `deliverable` is provided, also writes a task-bound result artifact
@@ -1,6 +1,6 @@
1
1
  import { ArtifactsClient, updateTaskState, } from '@ziggs-ai/api-client';
2
2
  /**
3
- * Record a conformant report for a completed task (B2 — ZIG-562).
3
+ * Record a conformant report for a completed task (B2).
4
4
  *
5
5
  * Always sets Task.result via updateTaskState (the canonical done payload).
6
6
  * When `deliverable` is provided, also writes a task-bound result artifact
@@ -10,11 +10,11 @@ import { ArtifactsClient, updateTaskState, } from '@ziggs-ai/api-client';
10
10
  */
11
11
  export async function recordReport(input) {
12
12
  const { creds, taskId, report, chatId, agreementId, deliverable } = input;
13
- // ZIG-1037: no container needed. The deliverable is bound to its task, which
13
+ // no container needed. The deliverable is bound to its task, which
14
14
  // is what makes it retrievable as `via=task:<taskId>` and readable by the
15
15
  // task's parties — a chat or agreement was never what made that work.
16
16
  //
17
- // ZIG-1075: the agreement still wins here, and this is now the ONE place that
17
+ // the agreement still wins here, and this is now the ONE place that
18
18
  // resolves rather than refuses — deliberately, because the caller is not a
19
19
  // model choosing arguments. `recordReport` is handed both ids by the runtime
20
20
  // (the task's agreement and the chat it is running in), so there is no
package/dist/types.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * One outcome vocabulary, one ctx shape, one transition signature.
5
5
  * Every state — parked or thinking — re-enters with exactly one Outcome.
6
6
  */
7
+ import type { AgentNeed } from './tools/needs.js';
7
8
  export interface AgreementRef {
8
9
  agreementId: string;
9
10
  parties?: {
@@ -70,7 +71,7 @@ export type Outcome = {
70
71
  } | {
71
72
  kind: 'task-closed';
72
73
  status: 'completed' | 'failed';
73
- /** Task being closed — required to clear only that entry (ZIG-977). */
74
+ /** Task being closed — required to clear only that entry. */
74
75
  taskId?: string;
75
76
  result?: unknown;
76
77
  } | {
@@ -95,7 +96,7 @@ export type Outcome = {
95
96
  */
96
97
  proposedByMe: boolean;
97
98
  /**
98
- * ZIG-1278 — true when the wake was a chat-less store/listing claim
99
+ * true when the wake was a chat-less store/listing claim
99
100
  * (`resource_changed` + `reason === 'proposal_approved'`). Distinguishes
100
101
  * the provider claim-kickoff (open chat + greet) from a direct-proposal
101
102
  * counterparty approve, which must never auto-kickoff.
@@ -162,7 +163,7 @@ export interface CollectedSubtaskResult {
162
163
  }
163
164
  /**
164
165
  * Per-assigned-task (or coordinator-lane) bookkeeping under one chat lane.
165
- * Keyed on Ctx.tasks by taskId (ZIG-977) — task-closed clears only its entry.
166
+ * Keyed on Ctx.tasks by taskId — task-closed clears only its entry.
166
167
  */
167
168
  export interface TaskBookkeeping {
168
169
  agreementId: string | null;
@@ -179,7 +180,7 @@ export interface TaskBookkeeping {
179
180
  * Task bookkeeping lives in `tasks` (keyed by taskId). `activeTaskId` /
180
181
  * `activeAgreementId` are the focus scalars for prompt + FSM convenience —
181
182
  * assigning task B no longer destroys task A's pending/collected state, and
182
- * closing A leaves B intact (ZIG-977).
183
+ * closing A leaves B intact.
183
184
  */
184
185
  export interface Ctx {
185
186
  identity: Identity;
@@ -202,7 +203,7 @@ export interface Ctx {
202
203
  * Recent wake timestamps (epoch ms) for this lane (claude-sdk cognition
203
204
  * only). Backstop circuit breaker: if a lane wakes faster than any real
204
205
  * traffic could drive it, the brain skips the LLM instead of burning the
205
- * fleet key on a wake storm.
206
+ * key on a wake storm.
206
207
  */
207
208
  recentDeliveries?: number[];
208
209
  }
@@ -276,7 +277,7 @@ export interface ThinkingState {
276
277
  allowNoWait?: boolean;
277
278
  }
278
279
  /**
279
- * ZIG-764: fixed tool invoke with no LLM turn. Entered after transitions
280
+ * fixed tool invoke with no LLM turn. Entered after transitions
280
281
  * (e.g. task-assigned → executing); runs `tool` once and emits `produces`.
281
282
  */
282
283
  export interface MechanicalState {
@@ -340,7 +341,7 @@ export interface ContextSnapshot {
340
341
  * 404'd) — deleted or never visible to this agent. Message-triggered wakes
341
342
  * check this and skip the LLM instead of reasoning over a fabricated empty
342
343
  * history. Only gates message wakes. A bare agreementId as sessionId also
343
- * trips it (ZIG-975) — that is a mis-keyed lane, not a legitimate task lane;
344
+ * trips it — that is a mis-keyed lane, not a legitimate task lane;
344
345
  * task wakes should key on the agreement's origin/notification chat.
345
346
  */
346
347
  chatMissing?: boolean;
@@ -364,7 +365,7 @@ export interface ToolCallResult {
364
365
  /**
365
366
  * Summed token usage of any nested LLM call the tool made (e.g. llmTool).
366
367
  * Threaded up so the turn's authoritative token count (machine.tokens ->
367
- * result.metrics) includes tool-internal spend rather than leaking it (ZIG-813).
368
+ * result.metrics) includes tool-internal spend rather than leaking it.
368
369
  */
369
370
  usage?: LlmResponse['usage'];
370
371
  }
@@ -385,7 +386,7 @@ export interface DeliveryWriteKeys {
385
386
  readonly wakeKey: string | null;
386
387
  /**
387
388
  * Key for an artifact write of this wake. Pass the artifact's content so the
388
- * key is derived from it (ZIG-1045 semantics): a wake writing several
389
+ * key is derived from it (semantics): a wake writing several
389
390
  * artifacts gets several keys, and a redelivered wake that re-writes the same
390
391
  * content reuses its key instead of colliding on an ordinal slot and being
391
392
  * discarded. Omitting content falls back to a per-wake ordinal — call exactly
@@ -397,7 +398,7 @@ export interface DeliveryWriteKeys {
397
398
  /**
398
399
  * Default messageId for a chat-message send of this wake — the backend dedups
399
400
  * on (chatId, messageId). Derived from the emission's content (text + chat +
400
- * receiver), not a per-wake ordinal (ZIG-1045): a wake that says two things
401
+ * receiver), not a per-wake ordinal: a wake that says two things
401
402
  * gets two keys, and a redelivered wake that re-says the same text reuses the
402
403
  * same key, while a re-think with different text does not collide and drop.
403
404
  */
@@ -437,11 +438,11 @@ export type Effect = {
437
438
  kind: 'llm-call';
438
439
  messages: LlmMessage[];
439
440
  tools: LlmToolSchema[];
440
- /** Chat/session id for monitoring ingest (ZIG-360). */
441
+ /** Chat/session id for monitoring ingest. */
441
442
  sessionId?: string;
442
- /** Per-turn UUID grouping all LLM + tool calls in one turn (ZIG-440). */
443
+ /** Per-turn UUID grouping all LLM + tool calls in one turn. */
443
444
  runId?: string;
444
- /** FSM state name at the time of this call (ZIG-440). */
445
+ /** FSM state name at the time of this call. */
445
446
  stateId?: string;
446
447
  } | {
447
448
  kind: 'stream-text';
@@ -459,15 +460,15 @@ export type Effect = {
459
460
  senderId?: string;
460
461
  senderType?: string;
461
462
  /**
462
- * Agreement this tool call is acting under (ZIG-831). For a delegated
463
+ * Agreement this tool call is acting under. For a delegated
463
464
  * per-user MCP call, `senderId` is the delegating agent, not the end-user
464
465
  * who owns the connection; this lets the gateway resolve the delegation
465
466
  * root's user. Sourced from the waking task event's `result.agreementId`.
466
467
  */
467
468
  onBehalfOfAgreementId?: string;
468
- /** Per-turn UUID (ZIG-440). */
469
+ /** Per-turn UUID. */
469
470
  runId?: string;
470
- /** FSM state name (ZIG-440). */
471
+ /** FSM state name. */
471
472
  stateId?: string;
472
473
  /** Replay-stable write keys for this wake — write-capable tools derive their idempotency key from here, never from the LLM. */
473
474
  writeKeys?: DeliveryWriteKeys;
@@ -484,7 +485,7 @@ export type Effect = {
484
485
  idempotencyKey?: string;
485
486
  };
486
487
  /**
487
- * Typed result map. With this shape, `await eff({ kind: 'read-context', ... })`
488
+ * Typed result map. With this shape, `await eff({ kind: 'read-context', .. })`
488
489
  * resolves to `ContextSnapshot`, not a union — the discriminant carries the
489
490
  * result type. Tests and Server impls implement this map exhaustively.
490
491
  */
@@ -520,7 +521,7 @@ export interface DefineAgentInput {
520
521
  /**
521
522
  * Human-facing one-liner: what this agent does, for a buyer reading the store
522
523
  * row. NOT the system prompt — a claude-sdk agent puts its prompt in
523
- * `systemPrompt` (ZIG-1080: every claude-sdk agent used to pass its prompt
524
+ * `systemPrompt` (every claude-sdk agent used to pass its prompt
524
525
  * here, and `deriveAgentRecord` published it straight to the store).
525
526
  */
526
527
  description: string;
@@ -534,6 +535,13 @@ export interface DefineAgentInput {
534
535
  initial: string;
535
536
  states: Record<string, State>;
536
537
  tools?: unknown[];
538
+ /**
539
+ * Access this agent cannot work without. Declaring a need PRODUCES the tools
540
+ * for it — do not also hand-list them — and makes work that arrives without
541
+ * the grant fail at task start with the missing thing named, instead of
542
+ * part-way through a real hire.
543
+ */
544
+ needs?: AgentNeed[];
537
545
  services?: ServicesConfig;
538
546
  operatorKey?: string;
539
547
  taskTools?: 'all' | 'none' | string[];
@@ -557,6 +565,8 @@ export interface AgentConfig {
557
565
  systemPrompt?: string;
558
566
  specialization?: string;
559
567
  tools: unknown[];
568
+ /** Normalized declared needs — see DefineAgentInput.needs. */
569
+ needs?: AgentNeed[];
560
570
  model: string;
561
571
  workflow: Workflow;
562
572
  services?: ServicesConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/agent-sdk",
3
- "version": "0.10.8",
3
+ "version": "0.11.1",
4
4
  "description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "scripts": {
19
19
  "build": "tsc -p tsconfig.json",
20
- "prepack": "npm run build",
20
+ "prepack": "rm -rf dist && npm run build",
21
21
  "typecheck": "tsc -p tsconfig.json --noEmit",
22
22
  "test": "node --experimental-test-module-mocks --import tsx/esm --test --test-reporter=spec test/*.test.ts",
23
23
  "test:watch": "node --experimental-test-module-mocks --import tsx/esm --test --watch test/*.test.ts"
@@ -26,7 +26,7 @@
26
26
  "@anthropic-ai/claude-agent-sdk": "^0.3.204",
27
27
  "@anthropic-ai/sdk": "^0.110.0",
28
28
  "@modelcontextprotocol/sdk": "^1.29.0",
29
- "@ziggs-ai/api-client": "0.9.8",
29
+ "@ziggs-ai/api-client": "0.10.4",
30
30
  "ajv": "^8.17.1",
31
31
  "dotenv": "^17.2.3",
32
32
  "openai": "^4.0.0",