@ziggs-ai/agent-sdk 0.1.8 → 0.1.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ziggs-ai/agent-sdk",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -103,8 +103,17 @@ function mapMcpTools(client: Client, tools: McpTool[]): ToolDefinition[] {
103
103
  * await closeMcp();
104
104
  * });
105
105
  */
106
- function buildDefaultWorkflow(description: string): Workflow {
106
+ function buildDefaultWorkflow(description: string, mcpTools: McpTool[]): Workflow {
107
107
  const dflt = thinkingDefaults({ initial: 'idle' });
108
+ // Bind each MCP tool as an explicit action so runTurn includes them in the
109
+ // LLM API call and the decision schema. Without this, allowedToolNames is
110
+ // empty and the tools array passed to the LLM is also empty.
111
+ const toolActions = Object.fromEntries(
112
+ mcpTools.map(t => [t.name, {
113
+ tool: t.name,
114
+ prompt: { when: t.description || `Use ${t.name}` },
115
+ }]),
116
+ );
108
117
  return {
109
118
  id: 'mcp-agent',
110
119
  description: description || 'MCP-backed agent',
@@ -115,10 +124,31 @@ function buildDefaultWorkflow(description: string): Workflow {
115
124
  prompt: {
116
125
  role: 'You are a helpful agent powered by an MCP server.',
117
126
  goal: description || 'Help the user by calling the available tools.',
118
- constraints: 'Use your tools to answer requests. When no action is needed, wait.',
127
+ constraints: 'Use your tools to answer the user\'s request. After gathering results, use "respond" to send the answer. Use "wait" only when no action is needed.',
119
128
  },
120
- actions: { ...dflt.actions },
121
- transitions: [...dflt.transitions],
129
+ actions: {
130
+ ...dflt.actions,
131
+ ...toolActions,
132
+ respond: {
133
+ prompt: {
134
+ instruction: 'Send your final answer to the user.',
135
+ when: 'You have gathered enough information and are ready to reply to the user.',
136
+ format: 'args: { receiverId: "<userId>", message: "<your answer>" }',
137
+ },
138
+ produces: 'message-sent',
139
+ },
140
+ },
141
+ transitions: [
142
+ { to: 'idle', when: (o) => o.kind === 'wait' },
143
+ { to: 'idle', when: (o) => o.kind === 'error' },
144
+ { to: 'done', when: (o) => o.kind === 'message-sent' },
145
+ ],
146
+ },
147
+ done: {
148
+ kind: 'parked',
149
+ transitions: [
150
+ { to: 'idle', when: (o) => o.kind === 'message-received' },
151
+ ],
122
152
  },
123
153
  },
124
154
  };
@@ -157,7 +187,7 @@ export async function createMcpAgent(options: CreateMcpAgentOptions): Promise<Mc
157
187
  const { tools: rawTools } = await client.listTools();
158
188
  const mcpTools = mapMcpTools(client, rawTools as McpTool[]);
159
189
 
160
- const resolvedWorkflow = workflow ?? buildDefaultWorkflow(hostOptions.description ?? '');
190
+ const resolvedWorkflow = workflow ?? buildDefaultWorkflow(hostOptions.description ?? '', rawTools as McpTool[]);
161
191
 
162
192
  const host = new AgentHost({
163
193
  ...hostOptions,
@@ -169,7 +169,7 @@ export function validateWorkflow(workflow: Workflow): ValidationResult {
169
169
  });
170
170
  if (!hasErrorFallthrough) {
171
171
  warnings.push(
172
- `thinking state "${name}" has no fallthrough for { kind: 'error' } — empty/failed turns may silently recurse until the depth guard (ZIG-303). Add an error transition or spread thinkingDefaults().transitions.`,
172
+ `thinking state "${name}" has no fallthrough for { kind: 'error' } — empty/failed turns may silently recurse until the depth guard. Add an error transition or spread thinkingDefaults().transitions.`,
173
173
  );
174
174
  }
175
175
  }
@@ -42,6 +42,5 @@ export {
42
42
  export {
43
43
  CONTEXT_TOOLS,
44
44
  contextDiscoverTool,
45
- contextListGrantsTool,
46
45
  contextDelegateTool,
47
46
  } from './tier2/contextTools.js';
@@ -32,6 +32,7 @@ interface ProtocolPayload {
32
32
  parentAgreementId?: string;
33
33
  parentTaskId?: string;
34
34
  taskId?: string;
35
+ assigneeId?: string;
35
36
  status?: string;
36
37
  result?: unknown;
37
38
  plan?: unknown;
@@ -95,6 +96,7 @@ export async function dispatchProtocolOp(
95
96
  plan: payload.plan,
96
97
  planReviewTiming: payload.planReviewTiming,
97
98
  requireMidWorkPlanAck: payload.requireMidWorkPlanAck,
99
+ assigneeId: payload.assigneeId,
98
100
  });
99
101
  case 'task-update':
100
102
  if (!payload.taskId || !payload.status) return null;
@@ -87,9 +87,9 @@ export const taskUpdatePlanStepTool: ToolDefinition = defineTool(
87
87
 
88
88
  export const taskSpawnTool: ToolDefinition = defineTool(
89
89
  'task_spawn',
90
- { agreementId: { type: 'string', required: true }, description: { type: 'string', required: true }, parentTaskId: 'string', plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' },
90
+ { agreementId: { type: 'string', required: true }, description: { type: 'string', required: true }, parentTaskId: 'string', assigneeId: { type: 'string', description: 'Explicitly hand this task to one specific agent (e.g. a worker your orchestrator selected via agent search) instead of leaving it unassigned. Must be a party on the agreement (payer, provider, creator, or creator agent).' }, plan: { type: 'object' }, planReviewTiming: 'string', requireMidWorkPlanAck: 'boolean' },
91
91
  handlerFor('task-spawn'),
92
- { description: 'Spawn a new task under an existing approved agreement. Use when the contract is already in place.' },
92
+ { description: 'Spawn a new task under an existing approved agreement. Use when the contract is already in place. Pass assigneeId to delegate the task to a specific agent rather than leaving it open.' },
93
93
  );
94
94
 
95
95
  export const PROTOCOL_TOOLS: ToolDefinition[] = [
@@ -18,17 +18,7 @@ export const contextDiscoverTool: ToolDefinition = defineTool(
18
18
  async (_args, ctx) => clientFor(ctx as Ctx).discover(),
19
19
  {
20
20
  description:
21
- 'List which chats, agreements, and org scopes this agent can reach via context grants (descriptors only — no message or artifact content).',
22
- },
23
- );
24
-
25
- export const contextListGrantsTool: ToolDefinition = defineTool(
26
- 'context_list_grants',
27
- {},
28
- async (_args, ctx) => clientFor(ctx as Ctx).listGrants(),
29
- {
30
- description:
31
- 'List context grants held by this agent (grant ids and bounds). Does not fetch scoped content.',
21
+ 'List every context grant this agent holds, as scope descriptors — grantId, scope, temporal, watermarkAt, expiresAt (no message or artifact content).',
32
22
  },
33
23
  );
34
24
 
@@ -69,6 +59,5 @@ export const contextDelegateTool: ToolDefinition = defineTool(
69
59
 
70
60
  export const CONTEXT_TOOLS = [
71
61
  contextDiscoverTool,
72
- contextListGrantsTool,
73
62
  contextDelegateTool,
74
63
  ] as const;
@@ -69,14 +69,6 @@ export class ZiggsContextClient {
69
69
  return (res['reach'] as ContextReachDescriptor[]) || [];
70
70
  }
71
71
 
72
- /** List persisted grant rows held by this agent (may include signedBytes). */
73
- async listGrants(): Promise<unknown[]> {
74
- this.requireActAsAgent('listGrants');
75
- const res = (await this._get('/context/grants')) as Record<string, unknown>;
76
- const grants = (res['grants'] as Array<Record<string, unknown>>) || [];
77
- return grants.filter((g) => g['holderId'] === this.actAsAgentId);
78
- }
79
-
80
72
  /** Holder delegates a narrower child grant. */
81
73
  async delegate(params: DelegateContextGrantParams): Promise<unknown> {
82
74
  this.requireActAsAgent('delegate');