@standardagents/skill 0.16.0 → 0.16.1-next.1e58032

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": "@standardagents/skill",
3
- "version": "0.16.0",
3
+ "version": "0.16.1-next.1e58032",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -33,7 +33,7 @@ For deeper reference material that this skill links to, see:
33
33
 
34
34
  ## Before you write any code
35
35
 
36
- Most failed Standard Agent projects fail in the same six ways. Read this section first and answer all six questions explicitly before creating any code. Each links to the deeper section that explains *how*.
36
+ Most failed Standard Agent projects fail in the same seven ways. Read this section first and answer all seven questions explicitly before creating any code. Each links to the deeper section that explains *how*.
37
37
 
38
38
  **1. Architect the agent graph before picking types.**
39
39
  List the domains the system touches. Determine the tree (coordinator → domain agents → sub-domain agents). *Then* decide what each node is. Do not start by writing one agent and bolting tools onto it. → [Architecture & decomposition](#architecture--decomposition)
@@ -53,6 +53,9 @@ Fetch the official current docs. Confirm auth, base URL, endpoint paths, payload
53
53
  **6. Check `ThreadState` before adding any dependency.**
54
54
  Before reaching for S3, Redis, an external cron, a queue service, or even `node:fs`, confirm the framework does not already provide the capability via `ThreadState`. It almost always does. → [ThreadState first](#threadstate-first)
55
55
 
56
+ **7. Ship complete, polished definitions — not skeletons.**
57
+ A new agent is not done when it typechecks. It is done when it has a specific name, a `description`, an `icon`, human side labels, session tools wired in all three required places, and a prompt that handles the realistic edge cases of its domain. → [Creating a new agent: the completeness bar](#creating-a-new-agent-the-completeness-bar)
58
+
56
59
  ---
57
60
 
58
61
  ## What is a Standard Agent?
@@ -253,6 +256,140 @@ A `dual_ai` agent with no `sessionStop`, no `sessionFail`, and no `maxSessionTur
253
256
 
254
257
  ---
255
258
 
259
+ ## Creating a new agent: the completeness bar
260
+
261
+ The most common quality failure when a coding agent creates a Standard Agent is **shipping a skeleton**: a bare `name`, no icon, sides called "Side A" and "Side B", a two-sentence prompt, and session tools that are bound on the agent but missing from the prompt's tool list. The agent typechecks, runs once, and then behaves badly in every way that matters. Hold every new agent to the bar in this section before calling it done.
262
+
263
+ ### Identity & presentation (required, not optional)
264
+
265
+ | Field | Bar | Bad | Good |
266
+ |---|---|---|---|
267
+ | `name` | snake_case, domain + role. Suffix coordinators `_coordinator`, reviewers `_reviewer`, leaf agents `_agent`. | `assistant`, `my_agent`, `helper` | `gmail_agent`, `invoice_audit_reviewer`, `marketing_comms_coordinator` |
268
+ | `description` | One concrete sentence: what it does, for whom, with what. Shown in UIs. | "An agent that helps with email." | "Triages the support inbox, drafts replies for known issues, and escalates unknowns to a human queue." |
269
+ | `toolDescription` | Written for the **calling model**, not a human: when to choose this tool, what the key arguments are, what comes back. Required when `exposeAsTool: true`. | "Research agent." | "Research a topic with web search and source-backed URLs; returns a cited answer after an internal sufficiency review. Use for questions that need current or verifiable facts." |
270
+ | `icon` | Always set one. See below. | omitted | inline SVG data URI or hosted URL |
271
+ | `sideA.label` / `sideB.label` | Always set both on `dual_ai`. Name the **roles in the conversation** — they appear in the UI and logs. | "Side A" / "Side B", "AI 1" / "AI 2" | "Researcher" / "Reviewer", "Pilot" / "ATC", "Drafter" / "Editor", "Support" / "Customer" |
272
+
273
+ Side labels are also a design check: if you can't name the two roles, side_b probably doesn't have a real job yet — go back to [Session boundary discipline](#session-boundary-discipline).
274
+
275
+ ### Icons
276
+
277
+ Every agent gets an `icon`. Don't skip it because no asset exists — author one. The value is any image URL, and an inline SVG data URI is self-contained and needs no hosting:
278
+
279
+ ```ts
280
+ // agents/agents/invoice_audit_agent.ts
281
+ const icon = `data:image/svg+xml;utf8,${encodeURIComponent(
282
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
283
+ <rect width="32" height="32" rx="7" fill="#0f766e"/>
284
+ <path d="M10 9h12v14l-3-2-3 2-3-2-3 2z" fill="none" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/>
285
+ <path d="M13 14h6M13 18h4" stroke="#5eead4" stroke-width="2" stroke-linecap="round"/>
286
+ </svg>`,
287
+ )}`;
288
+ ```
289
+
290
+ Design rules for generated icons: one recognizable glyph for the domain (envelope for email, magnifier for research, calendar for scheduling), a filled rounded-square background in a single saturated color, two or three colors total, no text, no gradients, legible at 20×20. Give sibling agents in one project different background colors so they're distinguishable in the sidebar.
291
+
292
+ ### Session tools must exist in three places
293
+
294
+ A session-ending tool is not "configured" until it appears in **all three** of these places. Missing any one produces a broken agent that still typechecks:
295
+
296
+ 1. **`agents/tools/<name>.ts`** — a real `defineTool` whose args schema carries the payload fields (e.g. `final_answer`, `failure_summary`). The tool body can be a simple formatter; its job is to be callable and carry structured args.
297
+ 2. **The side's prompt `tools` array** — the model can only call tools listed at the active step. A `sessionStop` binding to a tool the prompt never offers means the session *can never end on purpose*; it burns `maxSessionTurns` and fails opaquely.
298
+ 3. **The `SideConfig` binding** — `sessionStop: { name: 'complete_research', messageProperty: 'final_answer' }`. Prefer the object form: `messageProperty` (and `attachmentsProperty` when files are returned) define the canonical payload the parent receives from a subagent. A bare string binding with no mapped property returns a vague payload upstream.
299
+
300
+ And a fourth, softer place: **the prompt text must tell the model when to call it** ("When the renders pass review, call `submit_video_assets` with ..."). Models do not infer termination protocol from tool names.
301
+
302
+ Quick failure-mode table:
303
+
304
+ | Symptom | Likely miss |
305
+ |---|---|
306
+ | Session always runs to `maxSessionTurns` | Session tool missing from the prompt's `tools` array, or prompt never says when to call it |
307
+ | Runtime error: unknown tool in session binding | Binding `name` typo, or tool file never created |
308
+ | Parent receives an empty / useless completion payload | `messageProperty` missing or doesn't match an arg field in the tool schema |
309
+ | Child fails but parent sees a "success" with garbage | No `sessionFail` bound — the model abused `sessionStop` to bail out |
310
+
311
+ ### Prompt quality rubric
312
+
313
+ A two-sentence system prompt is a skeleton, not a prompt. Every side's prompt should cover, roughly in this order:
314
+
315
+ 1. **Role and counterpart.** Who this side is *and who it is talking to*: "You are the researcher. The other participant is the user who needs the question answered." In `dual_ai`, each side must understand the other side's role or the conversation degrades into two assistants being polite to each other.
316
+ 2. **Objective and definition of done.** One sentence the model can test against: "Done means every factual claim has a source URL and the reviewer has approved."
317
+ 3. **Tool guidance.** When to use which tool — including the session tools: name them, say exactly what triggers calling them, and what belongs in each argument. For resumable subagents, distinguish `subagent_create` (new topic/instance) from `subagent_message` (follow-up to an existing instance).
318
+ 4. **Edge cases.** This is what separates a thoughtful prompt from a placeholder. Walk the domain and enumerate what realistically goes wrong, with an instruction for each. The recurring ones:
319
+ - *Empty or low-quality results* — retry differently, broaden, or report honestly? How many attempts before giving up?
320
+ - *Auth / permission / quota errors from tools* — never retry blindly; call `sessionFail` with what the operator must fix.
321
+ - *Ambiguous request* — ask the counterpart side, or make a stated assumption? Pick one and say so.
322
+ - *Partial success* — deliver the partial result with gaps called out, or fail? Define the threshold.
323
+ - *Out-of-scope or unsafe asks* — refuse and route where?
324
+ - *Conflicting instructions between turns* — which takes precedence?
325
+ 5. **Output format and quality bar.** Terse vs. comprehensive, citation requirements, structure of the final payload.
326
+ 6. **Negative space.** What the model must NOT do: don't echo secrets, don't call `complete_*` before review, don't invent IDs, don't message the parent for FYI-only info.
327
+
328
+ High-leverage extra: include one **worked contrast example** inside the prompt — "this answer is insufficient, this one is sufficient, here's why" — like the incomplete-news-list example in the repo's `web_research_reviewer` prompt. One concrete contrast outperforms three paragraphs of abstract criteria.
329
+
330
+ Anti-patterns: a prompt that just restates the tool list ("You have tools to search and finish"); termination instructions buried mid-paragraph; criteria written for a human reader instead of as decisions the model must make; the same prompt pasted on both sides with the labels swapped.
331
+
332
+ ### Subagent connection checklist
333
+
334
+ When the new agent is a child in a graph, creating the agent file is half the job. Verify the full wiring:
335
+
336
+ - [ ] Child is `dual_ai` with `exposeAsTool: true` and a calling-model-grade `toolDescription`
337
+ - [ ] Child has finite `maxSessionTurns`, and `sessionStop` + `sessionFail` bound on the side(s) that own those decisions
338
+ - [ ] The session tools pass the [three-places check](#session-tools-must-exist-in-three-places)
339
+ - [ ] The **parent prompt's `tools` array** has the subagent entry — an agent nobody references is unreachable. Choose `blocking` / `resumable` deliberately ([the four combinations](#subprompts-vs-subagents-vs-handoffs)), and map `initUserMessageProperty` (and `initAttachmentsProperty` for files) so the child starts with real context instead of an empty first turn
340
+ - [ ] The **parent prompt text** says when to delegate to this child and, if resumable, explains `subagent_create` vs `subagent_message`
341
+ - [ ] Side_b reviewers use a model from a *different provider* than side_a ([why](#session-boundary-discipline))
342
+ - [ ] Run the dev server and check the composition view: the parent→child edge should be visible, and creating a test thread should show the child spawn and the completion payload arrive back
343
+
344
+ ### Worked example: a complete minimal agent
345
+
346
+ This is the shape every new `dual_ai` agent should have on day one — identity, icon, labels, both session tools, wired prompts. (Compressed for space; real prompts should be longer per the rubric above.)
347
+
348
+ ```ts
349
+ // agents/tools/complete_audit.ts
350
+ export default defineTool({
351
+ description: 'Finish the audit session and return the findings to the requester.',
352
+ args: z.object({
353
+ findings: z.string().describe('Complete audit findings, ready for the requester.'),
354
+ discrepancy_count: z.number().describe('Number of discrepancies found.'),
355
+ }).strict(),
356
+ execute: async (_state, args) => ({ status: 'success' as const, result: args.findings }),
357
+ });
358
+
359
+ // agents/tools/fail_audit.ts — same shape, args: { failure_summary: z.string() }
360
+ ```
361
+
362
+ ```ts
363
+ // agents/agents/invoice_audit_agent.ts
364
+ export default defineAgent({
365
+ name: 'invoice_audit_agent',
366
+ type: 'dual_ai',
367
+ description: 'Audits uploaded invoices against purchase orders and reports discrepancies.',
368
+ icon: invoiceAuditIcon, // inline SVG data URI, see Icons above
369
+ maxSessionTurns: 16,
370
+ sideA: {
371
+ label: 'Auditor',
372
+ prompt: 'invoice_audit_worker',
373
+ sessionFail: { name: 'fail_audit', messageProperty: 'failure_summary' },
374
+ maxSteps: 8,
375
+ },
376
+ sideB: {
377
+ label: 'Controller',
378
+ prompt: 'invoice_audit_reviewer',
379
+ sessionStop: { name: 'complete_audit', messageProperty: 'findings' },
380
+ sessionFail: { name: 'fail_audit', messageProperty: 'failure_summary' },
381
+ maxSteps: 4,
382
+ },
383
+ exposeAsTool: true,
384
+ toolDescription:
385
+ 'Audit one or more invoices against purchase orders; returns findings with a discrepancy count after an internal controller review. Pass invoice file paths in attachments.',
386
+ });
387
+ ```
388
+
389
+ Both prompts list their session tools in `tools` and the reviewer prompt instructs: *"Approve by calling `complete_audit` with the full findings in `findings` only after every line item has been checked; if documents are unreadable or POs are missing after one clarification round, call `fail_audit` and name exactly what the requester must provide."* The parent prompt adds `{ name: 'invoice_audit_agent', initUserMessageProperty: 'request', initAttachmentsProperty: 'invoice_files' }` to its `tools` and explains when to delegate.
390
+
391
+ ---
392
+
256
393
  ## Model selection
257
394
 
258
395
  **Rule: never write a model string the user did not request and `current-models` did not produce.**
@@ -552,20 +689,23 @@ AgentDefinition
552
689
  sideA SideConfig AI side (or first AI in dual_ai)
553
690
  sideB SideConfig second AI side; required for dual_ai
554
691
  exposeAsTool boolean (default false) enables this agent to be called as a tool by other prompts
555
- toolDescription string required if exposeAsTool: true
556
- description string brief human description for UIs
557
- icon string URL or absolute path
692
+ toolDescription string required if exposeAsTool: true — write it for the calling model
693
+ description string brief human description for UIs — always set on new agents
694
+ icon string URL or inline SVG data URI — always set on new agents
558
695
  env Record<string, string> agent-level env values
559
696
  hooks HookId[] agent-scoped hooks (when prompts don't specify their own)
560
697
  ```
561
698
 
562
- `SideConfig` is where you bind `defaultPrompt`, `defaultModel`, and the **session lifecycle bindings**:
699
+ `SideConfig` is where you set the side's `label` and `prompt` and bind the **session lifecycle tools**:
563
700
 
564
- - `sessionStop` — name of the tool whose call ends the session with a result
565
- - `sessionFail` — name of the tool whose call ends the session with a failure
566
- - `sessionStatus` — optional, a tool used to update the session status mid-run
701
+ - `label` — the role name shown in the UI and logs ("Researcher", "Reviewer") — always set on `dual_ai` sides
702
+ - `prompt` — the prompt this side runs (references `agents/prompts/<name>`)
703
+ - `sessionStop` — tool whose call ends the session with a result; prefer `{ name, messageProperty }` so the payload is explicit
704
+ - `sessionFail` — tool whose call ends the session with a failure; same object form
705
+ - `sessionStatus` — optional, a tool used to publish status updates mid-run without ending the session
706
+ - `maxSteps` — per-side step cap within one turn
567
707
 
568
- These are the bindings the [Session boundary discipline](#session-boundary-discipline) section refers to. Every `dual_ai` agent must set them.
708
+ These are the bindings the [Session boundary discipline](#session-boundary-discipline) section refers to. Every `dual_ai` agent must set them, and every session tool must pass the [three-places check](#session-tools-must-exist-in-three-places).
569
709
 
570
710
  Packaging fields (`packageName`, `version`, `author`, `license`) exist for the agent packing system; ignore them unless you're publishing.
571
711