@andreprado/agentkit 0.1.0-alpha.5 → 0.1.0-alpha.7

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 (87) hide show
  1. package/README.md +9 -0
  2. package/docs/guides/add-channel.md +25 -0
  3. package/docs/guides/add-knowledge.md +134 -0
  4. package/docs/guides/agentkit-skills-architecture.md +471 -0
  5. package/docs/guides/channels-production-handoff.md +2 -0
  6. package/docs/guides/connect-telegram.md +17 -0
  7. package/docs/guides/connect-whatsapp-zapster.md +16 -0
  8. package/docs/guides/create-agent.md +10 -1
  9. package/docs/guides/run-evals.md +36 -1
  10. package/docs/llms-full.txt +90 -1
  11. package/docs/llms.txt +9 -2
  12. package/package.json +2 -1
  13. package/src/cli/cloud-client.ts +10 -2
  14. package/src/cli/commands/channels.ts +67 -3
  15. package/src/cli/commands/knowledge.ts +136 -0
  16. package/src/cli/deploy-chat-ui.ts +7 -0
  17. package/src/cli/deploy-readiness.ts +19 -0
  18. package/src/cli/help.ts +26 -2
  19. package/src/cli/index.ts +140 -8
  20. package/src/cloud/artifact.ts +92 -1
  21. package/src/cloud/contracts.ts +16 -0
  22. package/src/create-project.ts +38 -6
  23. package/src/index.ts +142 -1
  24. package/src/providers/pi.ts +1 -1
  25. package/src/providers/test.ts +1 -1
  26. package/src/runtime/channel-buffer.ts +30 -0
  27. package/src/runtime/channels.ts +1 -0
  28. package/src/runtime/chat.ts +21 -2
  29. package/src/runtime/config.ts +175 -0
  30. package/src/runtime/core/manifest.ts +37 -0
  31. package/src/runtime/database.ts +93 -2
  32. package/src/runtime/db-commands.ts +9 -0
  33. package/src/runtime/deploy-readiness.ts +12 -0
  34. package/src/runtime/dev-server.ts +201 -11
  35. package/src/runtime/evals.ts +210 -20
  36. package/src/runtime/inspect.ts +39 -0
  37. package/src/runtime/knowledge/chunk.ts +333 -0
  38. package/src/runtime/knowledge/config.ts +135 -0
  39. package/src/runtime/knowledge/embeddings.ts +133 -0
  40. package/src/runtime/knowledge/ingest.ts +521 -0
  41. package/src/runtime/knowledge/prompt-policy.ts +30 -0
  42. package/src/runtime/knowledge/retrieve.ts +283 -0
  43. package/src/runtime/knowledge/schema.ts +56 -0
  44. package/src/runtime/knowledge/tool.ts +64 -0
  45. package/src/runtime/knowledge/vector.ts +258 -0
  46. package/src/runtime/spec.ts +152 -0
  47. package/src/runtime/sync.ts +144 -0
  48. package/src/runtime/targets/cloudflare/build.ts +514 -4
  49. package/src/runtime/tools.ts +121 -1
  50. package/src/runtime/traces.ts +41 -0
  51. package/src/storage/sqlite.ts +141 -0
  52. package/src/templates/blank.ts +16 -5
  53. package/src/templates/dentista.ts +17 -2
  54. package/src/templates/skills/agentkit-build-agent/SKILL.md +51 -0
  55. package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +20 -0
  56. package/src/templates/skills/agentkit-build-agent/templates/sales-qualifier.instructions.md +17 -0
  57. package/src/templates/skills/agentkit-build-agent/templates/support-agent.instructions.md +16 -0
  58. package/src/templates/skills/agentkit-capsule/SKILL.md +62 -0
  59. package/src/templates/skills/agentkit-capsule/references/docs-router.md +15 -0
  60. package/src/templates/skills/agentkit-channels/SKILL.md +62 -0
  61. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +58 -0
  62. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +37 -0
  63. package/src/templates/skills/agentkit-channels/references/telegram.md +37 -0
  64. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +37 -0
  65. package/src/templates/skills/agentkit-database/SKILL.md +45 -0
  66. package/src/templates/skills/agentkit-database/templates/appointments.schema.sql +15 -0
  67. package/src/templates/skills/agentkit-database/templates/leads.schema.sql +17 -0
  68. package/src/templates/skills/agentkit-deploy/SKILL.md +44 -0
  69. package/src/templates/skills/agentkit-evals/SKILL.md +60 -0
  70. package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +22 -0
  71. package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +14 -0
  72. package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +14 -0
  73. package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +18 -0
  74. package/src/templates/skills/agentkit-knowledge/SKILL.md +40 -0
  75. package/src/templates/skills/agentkit-knowledge/templates/faq.md +14 -0
  76. package/src/templates/skills/agentkit-knowledge/templates/policies.md +14 -0
  77. package/src/templates/skills/agentkit-knowledge/templates/prices.csv +3 -0
  78. package/src/templates/skills/agentkit-prompts/SKILL.md +45 -0
  79. package/src/templates/skills/agentkit-prompts/templates/knowledge-grounded-faq.instructions.md +11 -0
  80. package/src/templates/skills/agentkit-provider/SKILL.md +57 -0
  81. package/src/templates/skills/agentkit-security/SKILL.md +55 -0
  82. package/src/templates/skills/agentkit-tools/SKILL.md +36 -0
  83. package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +35 -0
  84. package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +37 -0
  85. package/src/templates/skills/agentkit-tools/examples/lookup-order.tool.md +46 -0
  86. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +52 -0
  87. package/src/templates/support.ts +15 -4
@@ -1,4 +1,4 @@
1
- import type { AgentTool, JsonSchema, ToolContext, ToolRuntimeContext } from "../index";
1
+ import type { AgentTool, JsonSchema, ToolContext, ToolRenderResult, ToolRuntimeContext } from "../index";
2
2
  import type { SqliteAgentKitStore } from "../storage/sqlite";
3
3
  import { createLocalDatabaseRunner } from "./database";
4
4
  import { AgentKitError } from "./errors";
@@ -14,6 +14,7 @@ export type ToolCallResult = {
14
14
  visibility: "user" | "internal";
15
15
  input: unknown;
16
16
  output: unknown;
17
+ rendered?: ToolRenderResult;
17
18
  };
18
19
 
19
20
  export type ToolRuntime = {
@@ -97,10 +98,13 @@ async function executeToolCall(
97
98
  validateSchema(output, tool.outputSchema, `tool "${tool.name}" output`);
98
99
  }
99
100
 
101
+ const rendered = renderToolOutput(tool, input, output, options.runtime);
102
+
100
103
  options.store.completeToolCall({
101
104
  toolCallId: toolCall.id,
102
105
  status: "completed",
103
106
  output,
107
+ rendered,
104
108
  secretValues,
105
109
  });
106
110
 
@@ -110,6 +114,7 @@ async function executeToolCall(
110
114
  visibility: tool.visibility ?? "user",
111
115
  input,
112
116
  output,
117
+ ...(rendered ? { rendered } : {}),
113
118
  };
114
119
  } catch (error) {
115
120
  const secretValues = collectConfiguredSecretValues(tool, options.env ?? process.env);
@@ -125,6 +130,121 @@ async function executeToolCall(
125
130
  }
126
131
  }
127
132
 
133
+ function renderToolOutput(
134
+ tool: AgentTool,
135
+ input: unknown,
136
+ output: unknown,
137
+ runtime: ToolRuntimeContext,
138
+ ): ToolRenderResult | undefined {
139
+ if (!tool.render) {
140
+ return undefined;
141
+ }
142
+
143
+ const rendered = tool.render(output, {
144
+ input,
145
+ runtime,
146
+ });
147
+
148
+ if (typeof rendered === "string") {
149
+ return { text: rendered };
150
+ }
151
+
152
+ if (!isRecord(rendered) || typeof rendered.text !== "string" || rendered.text.trim().length === 0) {
153
+ throw new AgentKitError("tool_validation_error", `tool "${tool.name}" render must return a non-empty text string.`);
154
+ }
155
+
156
+ if (rendered.blocks !== undefined) {
157
+ if (!Array.isArray(rendered.blocks)) {
158
+ throw new AgentKitError("tool_validation_error", `tool "${tool.name}" render.blocks must be an array when provided.`);
159
+ }
160
+
161
+ for (const [index, block] of rendered.blocks.entries()) {
162
+ validateRenderBlock(block, `tool "${tool.name}" render.blocks[${index}]`);
163
+ }
164
+ }
165
+
166
+ return {
167
+ text: rendered.text,
168
+ ...(rendered.blocks ? { blocks: rendered.blocks } : {}),
169
+ };
170
+ }
171
+
172
+ function validateRenderBlock(block: unknown, label: string): void {
173
+ if (!isRecord(block)) {
174
+ throw new AgentKitError("tool_validation_error", `${label} must be an object.`);
175
+ }
176
+
177
+ if (block.type === "text") {
178
+ if (typeof block.text !== "string" || block.text.trim().length === 0) {
179
+ throw new AgentKitError("tool_validation_error", `${label}.text must be a non-empty string.`);
180
+ }
181
+ return;
182
+ }
183
+
184
+ if (block.type === "card") {
185
+ if (typeof block.title !== "string" || block.title.trim().length === 0) {
186
+ throw new AgentKitError("tool_validation_error", `${label}.title must be a non-empty string.`);
187
+ }
188
+
189
+ validateOptionalString(block.subtitle, `${label}.subtitle`);
190
+ validateRenderFields(block.fields, `${label}.fields`);
191
+ validateRenderActions(block.actions, `${label}.actions`);
192
+ return;
193
+ }
194
+
195
+ throw new AgentKitError("tool_validation_error", `${label}.type must be "text" or "card".`);
196
+ }
197
+
198
+ function validateRenderFields(value: unknown, label: string): void {
199
+ if (value === undefined) {
200
+ return;
201
+ }
202
+
203
+ if (!Array.isArray(value)) {
204
+ throw new AgentKitError("tool_validation_error", `${label} must be an array when provided.`);
205
+ }
206
+
207
+ for (const [index, field] of value.entries()) {
208
+ if (!isRecord(field)) {
209
+ throw new AgentKitError("tool_validation_error", `${label}[${index}] must be an object.`);
210
+ }
211
+
212
+ validateRequiredString(field.label, `${label}[${index}].label`);
213
+ validateRequiredString(field.value, `${label}[${index}].value`);
214
+ }
215
+ }
216
+
217
+ function validateRenderActions(value: unknown, label: string): void {
218
+ if (value === undefined) {
219
+ return;
220
+ }
221
+
222
+ if (!Array.isArray(value)) {
223
+ throw new AgentKitError("tool_validation_error", `${label} must be an array when provided.`);
224
+ }
225
+
226
+ for (const [index, action] of value.entries()) {
227
+ if (!isRecord(action)) {
228
+ throw new AgentKitError("tool_validation_error", `${label}[${index}] must be an object.`);
229
+ }
230
+
231
+ validateRequiredString(action.label, `${label}[${index}].label`);
232
+ validateOptionalString(action.href, `${label}[${index}].href`);
233
+ }
234
+ }
235
+
236
+ function validateRequiredString(value: unknown, label: string): void {
237
+ if (typeof value !== "string" || value.trim().length === 0) {
238
+ throw new AgentKitError("tool_validation_error", `${label} must be a non-empty string.`);
239
+ }
240
+ }
241
+
242
+ function validateOptionalString(value: unknown, label: string): void {
243
+ if (value !== undefined && typeof value !== "string") {
244
+ throw new AgentKitError("tool_validation_error", `${label} must be a string when provided.`);
245
+ }
246
+ }
247
+
128
248
  function resolveToolSecrets(
129
249
  tool: AgentTool,
130
250
  env: Record<string, string | undefined>,
@@ -0,0 +1,41 @@
1
+ import type { ConversationRecord, StoredRun, StoredToolCall } from "../storage/sqlite";
2
+ import { openCapsuleStore } from "../storage/sqlite";
3
+ import { loadAgentCapsule } from "./config";
4
+ import { AgentKitError } from "./errors";
5
+
6
+ export type ConversationTrace = ConversationRecord & {
7
+ runs: ConversationTraceRun[];
8
+ };
9
+
10
+ export type ConversationTraceRun = StoredRun & {
11
+ toolCalls: StoredToolCall[];
12
+ };
13
+
14
+ export async function getConversationTraceFromCwd(cwd: string, conversationId: string): Promise<ConversationTrace> {
15
+ if (!conversationId) {
16
+ throw new AgentKitError("validation_error", "Missing conversation id.");
17
+ }
18
+
19
+ const capsule = await loadAgentCapsule(cwd);
20
+ const store = await openCapsuleStore(capsule);
21
+
22
+ try {
23
+ const conversation = store.getConversation(conversationId);
24
+
25
+ if (!conversation) {
26
+ throw new AgentKitError("conversation_not_found", `Conversation "${conversationId}" was not found.`);
27
+ }
28
+
29
+ const runs = store.listRunsForConversation(conversation.id).map((run) => ({
30
+ ...run,
31
+ toolCalls: store.listToolCallsForRun(run.id),
32
+ }));
33
+
34
+ return {
35
+ ...conversation,
36
+ runs,
37
+ };
38
+ } finally {
39
+ store.close();
40
+ }
41
+ }
@@ -6,6 +6,7 @@ import type { DatabaseArgs, DatabaseResult, DatabaseRow, DatabaseStatement } fro
6
6
  import type { AgentMessageRole, ProviderRunResult } from "../providers";
7
7
  import type { LoadedAgentCapsule } from "../runtime/config";
8
8
  import { AgentKitError } from "../runtime/errors";
9
+ import { KNOWLEDGE_MIGRATION_ID, KNOWLEDGE_SCHEMA_SQL } from "../runtime/knowledge/schema";
9
10
 
10
11
  export type ConversationSummary = {
11
12
  id: string;
@@ -41,12 +42,30 @@ export type StoredToolCall = {
41
42
  visibility: ToolCallVisibility;
42
43
  input: unknown;
43
44
  output: unknown;
45
+ rendered: unknown;
44
46
  status: ToolCallStatus;
45
47
  startedAt: string;
46
48
  completedAt: string | null;
47
49
  errorMessage: string | null;
48
50
  };
49
51
 
52
+ export type StoredRun = {
53
+ id: string;
54
+ conversationId: string | null;
55
+ provider: string;
56
+ model: string;
57
+ status: RunStatus;
58
+ usage: {
59
+ inputTokens: number | null;
60
+ outputTokens: number | null;
61
+ totalTokens: number | null;
62
+ };
63
+ startedAt: string;
64
+ completedAt: string | null;
65
+ errorCode: string | null;
66
+ errorMessage: string | null;
67
+ };
68
+
50
69
  export type PersistedChatRun = {
51
70
  conversationId: string;
52
71
  runId: string;
@@ -153,6 +172,17 @@ const MIGRATIONS = [
153
172
  ADD COLUMN visibility TEXT NOT NULL DEFAULT 'user';
154
173
  `,
155
174
  },
175
+ {
176
+ id: KNOWLEDGE_MIGRATION_ID,
177
+ sql: KNOWLEDGE_SCHEMA_SQL,
178
+ },
179
+ {
180
+ id: "0007_add_tool_call_rendered",
181
+ sql: `
182
+ ALTER TABLE tool_calls
183
+ ADD COLUMN rendered_json TEXT;
184
+ `,
185
+ },
156
186
  ] as const;
157
187
 
158
188
  export async function openCapsuleStore(capsule: LoadedAgentCapsule): Promise<SqliteAgentKitStore> {
@@ -457,6 +487,7 @@ export class SqliteAgentKitStore {
457
487
  toolCallId: string;
458
488
  status: ToolCallStatus;
459
489
  output?: unknown;
490
+ rendered?: unknown;
460
491
  completedAt?: string;
461
492
  errorMessage?: string;
462
493
  secretValues?: string[];
@@ -469,6 +500,7 @@ export class SqliteAgentKitStore {
469
500
  SET
470
501
  status = $status,
471
502
  output_json = $outputJson,
503
+ rendered_json = $renderedJson,
472
504
  completed_at = $completedAt,
473
505
  error_message = $errorMessage
474
506
  WHERE id = $toolCallId
@@ -478,6 +510,7 @@ export class SqliteAgentKitStore {
478
510
  $toolCallId: input.toolCallId,
479
511
  $status: input.status,
480
512
  $outputJson: input.output === undefined ? null : serializeJson(input.output, input.secretValues),
513
+ $renderedJson: input.rendered === undefined ? null : serializeJson(input.rendered, input.secretValues),
481
514
  $completedAt: input.completedAt ?? new Date().toISOString(),
482
515
  $errorMessage: redactSecrets(input.errorMessage ?? null, input.secretValues),
483
516
  });
@@ -550,6 +583,35 @@ export class SqliteAgentKitStore {
550
583
  });
551
584
  }
552
585
 
586
+ listRunsForConversation(conversationId: string): StoredRun[] {
587
+ return this.sqlite(() => {
588
+ const rows = this.db
589
+ .prepare(
590
+ `
591
+ SELECT
592
+ id,
593
+ conversation_id,
594
+ provider,
595
+ model,
596
+ status,
597
+ input_tokens,
598
+ output_tokens,
599
+ total_tokens,
600
+ started_at,
601
+ completed_at,
602
+ error_code,
603
+ error_message
604
+ FROM runs
605
+ WHERE conversation_id = $conversationId
606
+ ORDER BY started_at ASC
607
+ `,
608
+ )
609
+ .all({ $conversationId: conversationId }) as SqliteRow[];
610
+
611
+ return rows.map(storedRunFromRow);
612
+ });
613
+ }
614
+
553
615
  listToolCallsForRun(runId: string): StoredToolCall[] {
554
616
  return this.sqlite(() => {
555
617
  const rows = this.db
@@ -563,6 +625,7 @@ export class SqliteAgentKitStore {
563
625
  visibility,
564
626
  input_json,
565
627
  output_json,
628
+ rendered_json,
566
629
  status,
567
630
  started_at,
568
631
  completed_at,
@@ -578,6 +641,54 @@ export class SqliteAgentKitStore {
578
641
  });
579
642
  }
580
643
 
644
+ applyApplicationMigrations(migrations: Array<{ id: string; sql: string }>): { applied: string[]; skipped: string[] } {
645
+ return this.sqlite(() => {
646
+ if (migrations.length === 0) {
647
+ return { applied: [], skipped: [] };
648
+ }
649
+
650
+ this.db.exec(`
651
+ CREATE TABLE IF NOT EXISTS agentkit_app_migrations (
652
+ id TEXT PRIMARY KEY,
653
+ applied_at TEXT NOT NULL
654
+ )
655
+ `);
656
+
657
+ const applied = new Set(
658
+ (
659
+ this.db.prepare("SELECT id FROM agentkit_app_migrations").all() as Array<{
660
+ id: string;
661
+ }>
662
+ ).map((row) => row.id),
663
+ );
664
+ const result = {
665
+ applied: [] as string[],
666
+ skipped: [] as string[],
667
+ };
668
+
669
+ for (const migration of migrations) {
670
+ if (applied.has(migration.id)) {
671
+ result.skipped.push(migration.id);
672
+ continue;
673
+ }
674
+
675
+ const statements = splitSqlStatements(migration.sql);
676
+ this.transaction(() => {
677
+ for (const statement of statements) {
678
+ this.db.exec(statement);
679
+ }
680
+
681
+ this.db
682
+ .prepare("INSERT INTO agentkit_app_migrations (id, applied_at) VALUES ($id, $appliedAt)")
683
+ .run({ $id: migration.id, $appliedAt: new Date().toISOString() });
684
+ });
685
+ result.applied.push(migration.id);
686
+ }
687
+
688
+ return result;
689
+ });
690
+ }
691
+
581
692
  applyApplicationSchema(source: string): void {
582
693
  this.sqlite(() => {
583
694
  const statements = splitSqlStatements(source);
@@ -785,6 +896,31 @@ function storedMessageFromRow(row: SqliteRow): StoredMessage {
785
896
  };
786
897
  }
787
898
 
899
+ function storedRunFromRow(row: SqliteRow): StoredRun {
900
+ const status = String(row.status);
901
+
902
+ if (status !== "running" && status !== "completed" && status !== "failed") {
903
+ throw new AgentKitError("storage_error", `Invalid stored run status "${status}".`);
904
+ }
905
+
906
+ return {
907
+ id: String(row.id),
908
+ conversationId: row.conversation_id === null ? null : String(row.conversation_id),
909
+ provider: String(row.provider),
910
+ model: String(row.model),
911
+ status,
912
+ usage: {
913
+ inputTokens: nullableNumber(row.input_tokens),
914
+ outputTokens: nullableNumber(row.output_tokens),
915
+ totalTokens: nullableNumber(row.total_tokens),
916
+ },
917
+ startedAt: String(row.started_at),
918
+ completedAt: row.completed_at === null ? null : String(row.completed_at),
919
+ errorCode: row.error_code === null ? null : String(row.error_code),
920
+ errorMessage: row.error_message === null ? null : String(row.error_message),
921
+ };
922
+ }
923
+
788
924
  function storedToolCallFromRow(row: SqliteRow): StoredToolCall {
789
925
  const status = String(row.status);
790
926
  const visibility = String(row.visibility);
@@ -805,6 +941,7 @@ function storedToolCallFromRow(row: SqliteRow): StoredToolCall {
805
941
  visibility,
806
942
  input: parseStoredJson(row.input_json),
807
943
  output: row.output_json === null ? undefined : parseStoredJson(row.output_json),
944
+ rendered: row.rendered_json === null ? undefined : parseStoredJson(row.rendered_json),
808
945
  status,
809
946
  startedAt: String(row.started_at),
810
947
  completedAt: row.completed_at === null ? null : String(row.completed_at),
@@ -812,6 +949,10 @@ function storedToolCallFromRow(row: SqliteRow): StoredToolCall {
812
949
  };
813
950
  }
814
951
 
952
+ function nullableNumber(value: unknown): number | null {
953
+ return value === null || value === undefined ? null : Number(value);
954
+ }
955
+
815
956
  function parseStoredJson(value: unknown): unknown {
816
957
  if (typeof value !== "string") {
817
958
  return value;
@@ -147,11 +147,13 @@ When the owner opens this folder in Codex, Claude Code, or another coding agent
147
147
 
148
148
  Start building immediately:
149
149
 
150
- - Read \`AGENTKIT.md\` and the full docs path from \`npm run agentkit -- docs full\`.
150
+ - Start with \`skills/agentkit-capsule/SKILL.md\`, then use \`npm run agentkit -- docs llms\` as the docs router.
151
+ - Create or update \`AGENT_SPEC.md\` from the owner's request with \`npm run agentkit -- spec init --brief "<owner request>"\`; the owner should not fill this file by hand before work starts.
151
152
  - Infer the first useful version from the owner's request.
152
153
  - Edit \`prompts/instructions.md\` for the agent behavior.
153
154
  - Edit \`agentkit.config.ts\` for provider, tools, secrets, access, and storage.
154
155
  - Add TypeScript tools under \`tools/\` when the requested agent needs actions or external data.
156
+ - Add \`sync.ts\`, \`seed.sql\`, and ordered \`migrations/*.sql\` when the requested agent depends on external catalogs or production-shaped data changes.
155
157
  - Do not wait for a wizard or recipe. AgentKit provides the scaffold and contract; you decide the implementation from the owner's brief.
156
158
  - Ask follow-up questions only when missing information blocks a safe local implementation.
157
159
  - State assumptions in the final response.
@@ -162,6 +164,9 @@ Start building immediately:
162
164
  - \`npm run dev\`: run the local Agent Capsule runtime.
163
165
  - \`npm run chat -- --message "hello"\`: send one local chat message.
164
166
  - \`npm run eval\`: run agent evals.
167
+ - \`npm run agentkit -- spec check\`: verify the local agent implementation contract exists.
168
+ - \`npm run agentkit -- eval from-conversation <conversation-id>\`: turn a real conversation into a regression eval.
169
+ - \`npm run agentkit -- conversations trace <conversation-id>\`: inspect messages, runs, tool calls, inputs, outputs, rendered output, and final responses.
165
170
  - \`npm run agentkit -- tool <name> --input fixtures/input.json\`: run one registered tool directly.
166
171
  - \`npm run agentkit -- db migrate\`: apply internal migrations and \`schema.sql\` locally.
167
172
  - \`npm run agentkit -- db reset --yes\`: recreate the local SQLite database and reapply schema.
@@ -170,7 +175,8 @@ Start building immediately:
170
175
  - \`npm run agentkit -- inspect\`: print machine-readable capsule state.
171
176
  - \`printf %s "$VALUE" | npm run agentkit -- env set <NAME> --stdin\`: write a local secret value to ignored \`.env\` without putting it in shell history.
172
177
  - \`npm run agentkit -- env list\`: list local secret names without printing values.
173
- - \`npm run agentkit -- docs full\`: print the full AgentKit contract path.
178
+ - \`npm run agentkit -- docs llms\`: print the lightweight AgentKit docs router.
179
+ - \`npm run agentkit -- docs full\`: print the full AgentKit contract path only when a skill asks for it.
174
180
 
175
181
  ## Testing With A UI
176
182
 
@@ -211,7 +217,7 @@ export const myTool = defineTool({
211
217
 
212
218
  Use \`ctx.db\` as the canonical helper. \`ctx.database\` and \`ctx.storage.sql\` are aliases. Use \`ctx.db.batch([...])\` for atomic writes; local tools can also use \`ctx.db.transaction(async (tx) => ...)\`. Do not import local database drivers or Node-only APIs in tools. AgentKit owns local and hosted database routing.
213
219
 
214
- \`schema.sql\` is an idempotent bootstrap file in v1. Use \`CREATE TABLE IF NOT EXISTS\`, \`CREATE INDEX IF NOT EXISTS\`, and safe additive changes. AgentKit does not run destructive schema changes or ordered \`migrations/*.sql\` automatically yet.
220
+ \`schema.sql\` is an idempotent bootstrap file. Use \`CREATE TABLE IF NOT EXISTS\`, \`CREATE INDEX IF NOT EXISTS\`, and safe additive changes. Use ordered \`migrations/*.sql\` for production-shaped schema evolution; \`npm run agentkit -- db migrate\` applies unapplied local migrations before \`schema.sql\`.
215
221
 
216
222
  ## Hosted Deploy
217
223
 
@@ -251,8 +257,10 @@ Example owner request:
251
257
  Turn the request into a working local capsule:
252
258
 
253
259
  - Update \`prompts/instructions.md\` with domain-specific behavior, boundaries, intake questions, and escalation rules.
260
+ - Create or update \`AGENT_SPEC.md\` with \`npm run agentkit -- spec init --brief "<owner request>"\`. The owner gives the general idea; the coding agent turns it into the structured contract.
254
261
  - Update \`agentkit.config.ts\` when tools, secrets, provider, or access rules change.
255
262
  - Add TypeScript tools under \`tools/\` for real actions or external data.
263
+ - Use \`npm run agentkit -- sync init\` when the agent needs catalog sync, fixture seed data, or ordered migrations.
256
264
  - Keep the first version runnable with \`test/fake\` unless the owner explicitly asks for a real provider.
257
265
  - Do not use a wizard or recipe. Build the capsule directly from the scaffold, the AgentKit contract, and the owner's brief.
258
266
  - Make practical assumptions and list them in your final response.
@@ -305,12 +313,14 @@ If you add a tool, also run a fake-provider tool smoke test:
305
313
  npm run agentkit -- tool tool_name --input '{}'
306
314
  \`\`\`
307
315
 
308
- For the full framework contract, read the path printed by:
316
+ For the lightweight docs router, read the path printed by:
309
317
 
310
318
  \`\`\`sh
311
- npm run agentkit -- docs full
319
+ npm run agentkit -- docs llms
312
320
  \`\`\`
313
321
 
322
+ Read the full framework contract with \`npm run agentkit -- docs full\` only when a skill asks for it.
323
+
314
324
  ## Hosted Deploy
315
325
 
316
326
  This capsule is hosted-deploy ready by default.
@@ -343,6 +353,7 @@ Use AgentKit conventions when editing this project.
343
353
  - Production secrets must be managed secrets, not committed files.
344
354
  - Keep required local secret names in \`.env.schema\` and values in ignored \`.env\`. AgentKit local commands load \`.env\` directly.
345
355
  - Treat the owner's natural-language request as the brief and start implementing inside this capsule.
356
+ - Start with \`skills/agentkit-capsule/SKILL.md\` when the task is not obvious.
346
357
  `,
347
358
  },
348
359
  {
@@ -857,6 +857,8 @@ Esta é uma AgentKit Agent Capsule para a Clara, atendente em português de um c
857
857
 
858
858
  A Clara conversa com clientes, coleta nome, email e telefone, consulta disponibilidade e agenda consultas em slots de 30 minutos. Ela também consulta e altera o próprio horário do cliente usando email e telefone como verificação mínima.
859
859
 
860
+ Quando o dono pedir mudanças em linguagem natural, crie ou atualize \`AGENT_SPEC.md\` com \`npm run agentkit -- spec init --brief "<pedido do dono>"\`. O dono dá a ideia geral; o agente de código transforma isso no contrato estruturado.
861
+
860
862
  ## Regras de Produto
861
863
 
862
864
  - Persona: Clara, atendente humana, simpática e objetiva.
@@ -885,9 +887,13 @@ A Clara conversa com clientes, coleta nome, email e telefone, consulta disponibi
885
887
  - \`npm run agentkit -- tool consultar_consulta --input '{"email":"ana@example.com","telefone":"11999999999"}'\`: consultar uma consulta.
886
888
  - \`npm run agentkit -- tool alterar_consulta --input '{"email":"ana@example.com","telefone":"11999999999","novaData":"2099-01-06","novoHorario":"10:30","confirmadoPeloCliente":true}'\`: alterar uma consulta confirmada.
887
889
  - \`npm run eval\`: rodar evals.
890
+ - \`npm run agentkit -- spec check\`: validar o contrato local da implementação.
891
+ - \`npm run agentkit -- eval from-conversation <conversation-id>\`: transformar uma conversa real em eval de regressão.
892
+ - \`npm run agentkit -- conversations trace <conversation-id>\`: inspecionar mensagens, runs, ferramentas, inputs, outputs, renderização e resposta final.
888
893
  - \`npm run dev\`: rodar a runtime local.
889
894
  - \`npm run agentkit -- inspect\`: imprimir o estado da cápsula.
890
- - \`npm run agentkit -- docs full\`: imprimir o contrato completo do AgentKit.
895
+ - \`npm run agentkit -- docs llms\`: imprimir o roteador leve da documentação AgentKit.
896
+ - \`npm run agentkit -- docs full\`: imprimir o contrato completo do AgentKit somente quando uma skill pedir.
891
897
 
892
898
  ## Teste Com UI
893
899
 
@@ -899,10 +905,12 @@ A Clara conversa com clientes, coleta nome, email e telefone, consulta disponibi
899
905
  ## Regras de Implementação
900
906
 
901
907
  - Use \`ctx.db\` nas ferramentas. Não importe drivers SQLite, Turso ou Node-only APIs.
902
- - Mantenha \`schema.sql\` idempotente com \`CREATE TABLE IF NOT EXISTS\` e \`CREATE INDEX IF NOT EXISTS\`.
908
+ - Mantenha \`schema.sql\` idempotente com \`CREATE TABLE IF NOT EXISTS\` e \`CREATE INDEX IF NOT EXISTS\`. Use \`migrations/*.sql\` ordenadas para evolução de schema com cara de produção.
909
+ - Use \`npm run agentkit -- sync init\` quando a agente depender de catálogo externo, fixture local ou seed padronizado.
903
910
  - Mantenha segredos em \`.env\`, nunca em arquivos versionados.
904
911
  - Não espere wizard ou recipe. AgentKit fornece o scaffold e o contrato; implemente diretamente conforme o brief do dono.
905
912
  - Para trocar para um provider real, o dono deve escolher OpenRouter, OpenAI, Anthropic ou outro provider suportado. Depois edite \`agentkit.config.ts\`, atualize \`.env.schema\` e configure secrets locais/hosted.
913
+ - Quando a próxima ação não for óbvia, comece por \`skills/agentkit-capsule/SKILL.md\`.
906
914
  `,
907
915
  },
908
916
  {
@@ -931,6 +939,13 @@ npm run chat -- --message "Oi, quero marcar uma consulta."
931
939
 
932
940
  A cápsula começa com \`test/fake\`. Isso valida caminhos determinísticos, mas não prova qualidade de conversa natural.
933
941
 
942
+ Se o dono pedir uma mudança grande, crie ou atualize o contrato de implementação:
943
+
944
+ \`\`\`sh
945
+ npm run agentkit -- spec init --brief "<pedido do dono>"
946
+ npm run agentkit -- spec check
947
+ \`\`\`
948
+
934
949
  ## Ferramentas
935
950
 
936
951
  - \`listar_horarios_disponiveis\`: recebe \`data\` em \`YYYY-MM-DD\` e retorna slots livres.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: agentkit-build-agent
3
+ description: Use when the owner gives a natural-language brief for a new or changed AgentKit agent and expects the coding agent to turn it into a working local capsule with prompts, tools, schema, evals, and verification.
4
+ ---
5
+
6
+ # Build An AgentKit Agent
7
+
8
+ Use this when the owner asks for an agent in plain language.
9
+
10
+ ## Workflow
11
+
12
+ 1. Read `agentkit.config.ts`, `prompts/instructions.md`, `schema.sql`, `evals/`, and existing `tools/`.
13
+ 2. If `AGENT_SPEC.md` does not exist, create it from the owner's plain-language request with `npm run agentkit -- spec init --brief "<owner request>"`. If it exists, update it directly before changing behavior.
14
+ 3. Infer the first useful local version from the owner's brief and the spec. Do not ask the owner to fill a form.
15
+ 4. Edit `prompts/instructions.md` for behavior, boundaries, intake questions, escalation rules, and tool-use policy.
16
+ 5. Add tools only when the agent needs action, live data, authorization-sensitive data, or durable writes.
17
+ 6. Add database tables to `schema.sql` or ordered `migrations/*.sql` when the agent owns records.
18
+ 7. Add `sync.ts` and `seed.sql` with `npm run agentkit -- sync init` when the agent depends on external catalogs or recurring imports.
19
+ 8. Add or update evals for the main flow. Prefer multi-turn `turns` evals for real conversations.
20
+ 9. Keep the capsule runnable on `test/fake` unless the owner has chosen a real provider.
21
+
22
+ ## Templates
23
+
24
+ Use these only when they match the brief:
25
+
26
+ - `templates/support-agent.instructions.md`
27
+ - `templates/appointment-intake.instructions.md`
28
+ - `templates/sales-qualifier.instructions.md`
29
+
30
+ For prompt-only work, use `skills/agentkit-prompts/SKILL.md`.
31
+ For database-backed tools, use `skills/agentkit-database/SKILL.md`.
32
+
33
+ ## Verification
34
+
35
+ ```sh
36
+ npm run typecheck
37
+ npm run agentkit -- inspect
38
+ npm run chat -- --message "hello"
39
+ npm run eval
40
+ npm run agentkit -- spec check
41
+ ```
42
+
43
+ If a tool was added:
44
+
45
+ ```sh
46
+ npm run agentkit -- tool <tool_name> --input '<json>'
47
+ ```
48
+
49
+ ## Final Response
50
+
51
+ Summarize the files changed, assumptions made, verification results, and whether the behavior was tested with `test/fake` or a real provider selected by the owner.
@@ -0,0 +1,20 @@
1
+ You are an appointment and intake agent.
2
+
3
+ Goal:
4
+ - Collect the information needed to understand the request.
5
+ - Offer available times only after checking availability through tools.
6
+ - Confirm the exact date, time, name, and contact details before saving.
7
+
8
+ Required intake:
9
+ - Full name
10
+ - Contact method
11
+ - Reason for visit
12
+ - Preferred date or time window
13
+ - Any urgency or special constraints
14
+
15
+ Rules:
16
+ - Do not diagnose, promise outcomes, or provide emergency guidance beyond directing urgent cases to appropriate human or emergency support.
17
+ - Do not create, change, or cancel an appointment without explicit user confirmation.
18
+ - Do not invent availability.
19
+ - Use the scheduling tools for availability and writes.
20
+
@@ -0,0 +1,17 @@
1
+ You are a sales qualification agent.
2
+
3
+ Goal:
4
+ - Understand the user's current situation, urgency, budget range, authority, and desired outcome.
5
+ - Identify whether the lead is a fit for the configured offer.
6
+ - Capture structured lead details through tools when available.
7
+
8
+ Behavior:
9
+ - Ask one focused question at a time.
10
+ - Avoid pressure and exaggerated claims.
11
+ - Be clear about what is known, unknown, and next.
12
+ - Escalate to a human when the user asks for pricing exceptions, legal terms, procurement details, or custom commitments.
13
+
14
+ Rules:
15
+ - Do not invent pricing, discounts, case studies, or availability.
16
+ - Do not expose internal lead scores or qualification labels.
17
+
@@ -0,0 +1,16 @@
1
+ You are a focused support agent.
2
+
3
+ Help users resolve the current issue clearly and efficiently.
4
+
5
+ Behavior:
6
+ - Ask for the minimum missing context needed to help.
7
+ - Use tools when order, account, booking, or case status is needed.
8
+ - Do not invent status, policy, price, or availability.
9
+ - Explain next steps in plain language.
10
+ - Escalate when the request involves billing disputes, safety, legal issues, account ownership, or anything outside the configured tools.
11
+
12
+ Boundaries:
13
+ - Do not claim to have changed anything unless a tool confirms it.
14
+ - Do not expose internal tool output, IDs, scores, secrets, or logs.
15
+ - If a tool fails, say what could not be verified and ask for a safe next step.
16
+