@andreprado/agentkit 0.1.0-alpha.21 → 0.1.0-alpha.23
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/docs/guides/add-managed-composio.md +3 -1
- package/docs/guides/add-tool.md +6 -3
- package/docs/guides/create-agent.md +6 -4
- package/docs/guides/prepare-deploy.md +1 -1
- package/docs/guides/run-evals.md +5 -1
- package/docs/guides/use-provider.md +26 -2
- package/docs/llms-full.txt +33 -5
- package/docs/llms.txt +4 -2
- package/package.json +1 -1
- package/src/cli/deploy-chat-ui.ts +86 -15
- package/src/cli/deploy-readiness.ts +80 -0
- package/src/cli/index.ts +129 -8
- package/src/index.ts +1 -1
- package/src/providers/pi.ts +12 -2
- package/src/runtime/chat.ts +7 -1
- package/src/runtime/config.ts +1 -1
- package/src/runtime/evals.ts +39 -24
- package/src/templates/blank.ts +29 -6
- package/src/templates/dentista.ts +22 -4
- package/src/templates/skills/agentkit-build-agent/SKILL.md +30 -2
- package/src/templates/skills/agentkit-capsule/SKILL.md +21 -0
- package/src/templates/skills/agentkit-database/SKILL.md +11 -0
- package/src/templates/skills/agentkit-deploy/SKILL.md +2 -0
- package/src/templates/skills/agentkit-evals/SKILL.md +15 -0
- package/src/templates/skills/agentkit-improve/SKILL.md +14 -4
- package/src/templates/skills/agentkit-integrations/SKILL.md +22 -0
- package/src/templates/skills/agentkit-provider/SKILL.md +20 -2
- package/src/templates/skills/agentkit-tools/SKILL.md +2 -0
- package/src/templates/support.ts +30 -7
|
@@ -79,7 +79,7 @@ Expected readiness:
|
|
|
79
79
|
|
|
80
80
|
## Connect Apps
|
|
81
81
|
|
|
82
|
-
After deploy, create a hosted Composio Connect Link:
|
|
82
|
+
The Composio connect link is deploy-scoped, so declare `composioManaged(...)` first, deploy, then connect. After deploy, create a hosted Composio Connect Link:
|
|
83
83
|
|
|
84
84
|
```sh
|
|
85
85
|
agentkit integrations connect composio --toolkit gmail
|
|
@@ -90,6 +90,8 @@ AgentKit prints a URL. Send that URL to the person who owns the app account.
|
|
|
90
90
|
|
|
91
91
|
If the deploy has only one toolkit, `--toolkit` can be omitted.
|
|
92
92
|
|
|
93
|
+
`agentkit deploy` prints the recommended `integrations connect composio --toolkit <slug>` command for each configured toolkit in its production handoff.
|
|
94
|
+
|
|
93
95
|
## Calendar Defaults
|
|
94
96
|
|
|
95
97
|
For Google Calendar agents, include read and write actions together. Do not expose only `GOOGLECALENDAR_CREATE_EVENT`; users naturally ask to see availability before booking.
|
package/docs/guides/add-tool.md
CHANGED
|
@@ -112,6 +112,8 @@ Direct tool test:
|
|
|
112
112
|
npm run agentkit -- tool lookup_order --input '{"orderId":"A100"}'
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
When the tool touches live data, writes externally, or enforces business rules, also add deterministic checks. Use fixtures, eval-safe branches, seed data, or direct tool inputs for success and failure paths such as missing confirmation, validation errors, provider 429s/timeouts, unavailable records, and privacy/no-leak behavior. Add an eval when the agent should call the tool with specific inputs or refuse to call it until required intake or confirmation is complete.
|
|
116
|
+
|
|
115
117
|
Expected output:
|
|
116
118
|
|
|
117
119
|
```json
|
|
@@ -129,9 +131,10 @@ Use this when a tool needs agent-owned tables and must work locally and after de
|
|
|
129
131
|
|
|
130
132
|
Recommended contract:
|
|
131
133
|
|
|
132
|
-
- Put
|
|
134
|
+
- Put the idempotent bootstrap view of agent-owned tables in `schema.sql`.
|
|
135
|
+
- For production-shaped schema evolution, add ordered `migrations/*.sql` files such as `migrations/0001_clients.sql`.
|
|
133
136
|
- Keep deploy-ready capsules on `storage.driver: "agentkit"`.
|
|
134
|
-
- Local `agentkit chat`, `agentkit tool`, `agentkit dev`, and eval runs apply
|
|
137
|
+
- Local `agentkit chat`, `agentkit tool`, `agentkit dev`, and eval runs apply ordered local migrations before `schema.sql`.
|
|
135
138
|
- Use `agentkit db migrate`, `agentkit db reset --yes`, `agentkit db seed [--file seed.sql]`, and `agentkit db shell` for local database setup and inspection.
|
|
136
139
|
- Hosted deploy migrates/provisions the managed database internally and applies the same `schema.sql`.
|
|
137
140
|
- Tools use `ctx.db` as the canonical helper. `ctx.database` and `ctx.storage.sql` are supported aliases.
|
|
@@ -176,7 +179,7 @@ CREATE TABLE IF NOT EXISTS appointments (
|
|
|
176
179
|
);
|
|
177
180
|
```
|
|
178
181
|
|
|
179
|
-
`schema.sql` is an idempotent bootstrap file
|
|
182
|
+
`schema.sql` is an idempotent bootstrap file. Prefer `CREATE TABLE IF NOT EXISTS`, `CREATE INDEX IF NOT EXISTS`, and safe additive `ALTER TABLE` statements. Use ordered `migrations/*.sql` for production-shaped schema evolution; `agentkit db migrate` applies unapplied local migrations before `schema.sql`.
|
|
180
183
|
|
|
181
184
|
`tools/schedule-appointment.ts`:
|
|
182
185
|
|
|
@@ -89,7 +89,7 @@ Runtime files created after chat:
|
|
|
89
89
|
|
|
90
90
|
## Handoff To A Coding Agent
|
|
91
91
|
|
|
92
|
-
The owner does not need to fill a separate brief file. The natural-language request they type into Codex, Claude Code, or another coding agent is the brief.
|
|
92
|
+
The owner does not need to run a brief wizard or fill a separate brief file. The natural-language request they type into Codex, Claude Code, or another coding agent is the brief.
|
|
93
93
|
|
|
94
94
|
Primary flow:
|
|
95
95
|
|
|
@@ -97,9 +97,9 @@ Primary flow:
|
|
|
97
97
|
Develop an appointment and intake agent for an ophthalmology office.
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
The generated `AGENTS.md`, `AGENTKIT.md`, `CLAUDE.md`, and `skills/` pack tell the coding agent which files to edit, which task skill to load, and which verification commands to run. There is no wizard
|
|
100
|
+
The generated `AGENTS.md`, `AGENTKIT.md`, `CLAUDE.md`, and `skills/` pack tell the coding agent which files to edit, which task skill to load, and which verification commands to run. There is no AgentKit CLI wizard in the normal flow: the coding agent edits the capsule directly from the scaffold, contract, and owner request. The default router is `skills/agentkit-capsule/SKILL.md`; `llms-full.txt` is reserved for complete-contract checks.
|
|
101
101
|
|
|
102
|
-
After the owner gives the general idea, the coding agent should create or update the implementation contract itself:
|
|
102
|
+
After the owner gives the general idea inside the coding-agent chat, the coding agent should create or update the implementation contract itself:
|
|
103
103
|
|
|
104
104
|
```sh
|
|
105
105
|
npm run agentkit -- spec init --brief "Develop an appointment and intake agent for an ophthalmology office."
|
|
@@ -108,6 +108,8 @@ npm run agentkit -- spec check
|
|
|
108
108
|
|
|
109
109
|
`AGENT_SPEC.md` is an internal working contract for the coding agent. It is not a form the owner must fill before work starts.
|
|
110
110
|
|
|
111
|
+
The coding agent should build a testable capsule, not only a prompt. For each meaningful requirement in the brief or `AGENT_SPEC.md`, decide whether it needs a prompt instruction, tool, schema/migration, fixture, eval, direct tool check, or deploy/readiness check. Privacy, confirmation, external writes, bookings, customer data, business hours, dates, and integration failures should have evals or deterministic checks before the capsule is called done.
|
|
112
|
+
|
|
111
113
|
Optional shortcut when copying a prompt into another coding agent:
|
|
112
114
|
|
|
113
115
|
```sh
|
|
@@ -176,7 +178,7 @@ npm run agentkit -- chat-ui --deploy
|
|
|
176
178
|
|
|
177
179
|
Open the printed `Chat:` URL and tell the owner this local UI is connected to the hosted deploy.
|
|
178
180
|
|
|
179
|
-
`test/fake` is deterministic. It validates the scaffold, direct tool checks, and fake-provider evals, but it does not validate natural conversation quality. Before claiming real conversation behavior is tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, or another supported provider.
|
|
181
|
+
`test/fake` is deterministic. It validates the scaffold, direct tool checks, and fake-provider evals, but it does not validate natural conversation quality. Before claiming real conversation behavior is tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, OpenCode Zen, OpenCode Go, or another supported provider.
|
|
180
182
|
|
|
181
183
|
## Safety Rules
|
|
182
184
|
|
|
@@ -154,7 +154,7 @@ npm run agentkit -- chat-ui --deploy
|
|
|
154
154
|
npm run agentkit -- access token list
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
For hosted deploys, `npm run agentkit -- deploy` writes the local chat/UI access token to `.agentkit/chat-access-token.json
|
|
157
|
+
For hosted deploys, `npm run agentkit -- deploy` writes the local chat/UI access token to `.agentkit/chat-access-token.json` and prints a production handoff with the deploy URL, UI command, secret status, database/schema artifact, integration connect commands, smoke status, and next recommended command. Use `npm run agentkit -- deploy --smoke "hello"` for the official hosted chat smoke, and use `npm run agentkit -- chat-ui --deploy` for hosted UI testing. The hosted Chat UI shows the conversation id, tool calls, tool errors, and a new-conversation control; use `npm run agentkit -- conversations trace <conversation-id> --deploy` to pull the hosted trace from the last deploy. Use `npm run agentkit -- access token create <name> --out <path>` only for additional clients.
|
|
158
158
|
|
|
159
159
|
When the UI is running, open the printed `Chat:` URL and tell the owner the exact URL. If the capsule is still on `test/fake`, say the UI was tested only with the deterministic fake provider.
|
|
160
160
|
|
package/docs/guides/run-evals.md
CHANGED
|
@@ -22,6 +22,8 @@ Run evals:
|
|
|
22
22
|
agentkit eval run
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
`agentkit eval run` uses temporary local SQLite storage for eval execution. This keeps eval conversations and tool calls isolated from `.agentkit/agentkit.db`, so evals can run while a local chat or dev server is using the normal development database.
|
|
26
|
+
|
|
25
27
|
If the capsule uses npm scripts and Windows PowerShell blocks `npm.ps1`, use:
|
|
26
28
|
|
|
27
29
|
```sh
|
|
@@ -54,6 +56,8 @@ Create or edit:
|
|
|
54
56
|
evals/<name>.eval.ts
|
|
55
57
|
```
|
|
56
58
|
|
|
59
|
+
Create evals proactively from the agent brief and `AGENT_SPEC.md`. High-value evals cover identity and scope, required intake fields, confirmation before writes, no-leak/privacy rules, timezone and business-hour behavior, default durations or limits, tool-call payloads, unavailable slots, empty results, missing auth, rate limits, and timeouts. If a real conversation reveals a bug, add the smallest regression eval that would have failed before the fix.
|
|
60
|
+
|
|
57
61
|
Use conversations as source material:
|
|
58
62
|
|
|
59
63
|
```txt
|
|
@@ -152,7 +156,7 @@ export default defineEval({
|
|
|
152
156
|
});
|
|
153
157
|
```
|
|
154
158
|
|
|
155
|
-
`tools.persisted` validates the tool call saved in local SQLite `tool_calls`, not a provider-specific raw response shape. It can be a tool name string or an object with `name`, `input`, `output`, `rendered`, `status`, and/or `visibility`.
|
|
159
|
+
`tools.persisted` validates the tool call saved in the eval run's local SQLite `tool_calls`, not a provider-specific raw response shape. It can be a tool name string or an object with `name`, `input`, `output`, `rendered`, `status`, and/or `visibility`.
|
|
156
160
|
|
|
157
161
|
Use `tools.count` for the exact number of persisted calls in that turn, `tools.calledOnce` for exactly one call by name, and `tools.order` for required relative order. `tools.order` allows extra calls before, between, or after the named calls; pair it with `tools.count` when the exact call set matters.
|
|
158
162
|
|
|
@@ -6,7 +6,7 @@ Switch a capsule from the offline `test/fake` provider to a Pi-backed provider.
|
|
|
6
6
|
|
|
7
7
|
## When To Use This
|
|
8
8
|
|
|
9
|
-
Use this when local fake responses are no longer enough and the agent needs model behavior from OpenRouter, OpenAI, Anthropic, or another supported provider.
|
|
9
|
+
Use this when local fake responses are no longer enough and the agent needs model behavior from OpenRouter, OpenAI, Anthropic, OpenCode Zen, OpenCode Go, or another supported provider.
|
|
10
10
|
|
|
11
11
|
The coding agent should not choose a real provider automatically. Ask the owner which provider to use, then update the capsule.
|
|
12
12
|
|
|
@@ -87,6 +87,30 @@ secrets: ["OPENROUTER_API_KEY"],
|
|
|
87
87
|
|
|
88
88
|
Prefer model ids or aliases listed by the installed Pi SDK when available, such as `~google/gemini-flash-latest`. If an OpenRouter model id is newer than the Pi model registry, AgentKit passes the id through to OpenRouter using Pi's OpenAI-compatible transport with conservative unknown-model metadata. The provider may still reject the request if the id is invalid, inaccessible, or does not support the tools/features the agent uses.
|
|
89
89
|
|
|
90
|
+
OpenCode Zen:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
provider: {
|
|
94
|
+
name: "opencode",
|
|
95
|
+
model: "big-pickle",
|
|
96
|
+
},
|
|
97
|
+
secrets: ["OPENCODE_API_KEY"],
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Use an OpenCode Zen model id listed by the installed Pi SDK, such as `big-pickle`, `deepseek-v4-flash-free`, `claude-sonnet-4-5`, or `gpt-5.4-mini`. OpenCode Zen uses `OPENCODE_API_KEY`.
|
|
101
|
+
|
|
102
|
+
OpenCode Go:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
provider: {
|
|
106
|
+
name: "opencode-go",
|
|
107
|
+
model: "deepseek-v4-flash",
|
|
108
|
+
},
|
|
109
|
+
secrets: ["OPENCODE_API_KEY"],
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Use an OpenCode Go model id listed by the installed Pi SDK, such as `deepseek-v4-flash`, `deepseek-v4-pro`, `glm-5.1`, `kimi-k2.6`, `minimax-m2.7`, or `qwen3.6-plus`. OpenCode Go also uses `OPENCODE_API_KEY`.
|
|
113
|
+
|
|
90
114
|
## UI Verification
|
|
91
115
|
|
|
92
116
|
After the provider is configured and the local secret is set, test through chat and UI:
|
|
@@ -135,7 +159,7 @@ npm run agentkit -- inspect
|
|
|
135
159
|
|
|
136
160
|
`provider_model_unsupported`:
|
|
137
161
|
|
|
138
|
-
For OpenAI or
|
|
162
|
+
For OpenAI, Anthropic, OpenCode Zen, or OpenCode Go, use a model id known to the installed Pi SDK for that provider. For OpenRouter, prefer a known Pi alias when possible; otherwise a raw OpenRouter model id is passed through and any remaining model error comes from OpenRouter.
|
|
139
163
|
|
|
140
164
|
Provider returns auth failure:
|
|
141
165
|
|
package/docs/llms-full.txt
CHANGED
|
@@ -161,7 +161,7 @@ Then open the folder in Codex, Claude Code, or another coding agent and ask dire
|
|
|
161
161
|
Develop an appointment and intake agent for an ophthalmology office.
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
The coding agent should infer the first useful version, edit `prompts/instructions.md`, `agentkit.config.ts`, `schema.sql`, `tools/`, and `evals/`, then run the verification commands before finishing. Do not
|
|
164
|
+
The coding agent should infer the first useful version, edit `prompts/instructions.md`, `agentkit.config.ts`, `schema.sql`, `tools/`, and `evals/`, then run the verification commands before finishing. Do not send the owner back to a CLI brief wizard. AgentKit provides the scaffold, contract, and skills; the coding agent implements directly in the capsule from the owner's chat message.
|
|
165
165
|
|
|
166
166
|
Optional handoff shortcut:
|
|
167
167
|
|
|
@@ -217,6 +217,8 @@ test
|
|
|
217
217
|
openai
|
|
218
218
|
anthropic
|
|
219
219
|
openrouter
|
|
220
|
+
opencode
|
|
221
|
+
opencode-go
|
|
220
222
|
custom
|
|
221
223
|
```
|
|
222
224
|
|
|
@@ -227,6 +229,8 @@ test/fake
|
|
|
227
229
|
openai via Pi SDK
|
|
228
230
|
anthropic via Pi SDK
|
|
229
231
|
openrouter via Pi SDK
|
|
232
|
+
opencode via Pi SDK
|
|
233
|
+
opencode-go via Pi SDK
|
|
230
234
|
```
|
|
231
235
|
|
|
232
236
|
`custom` is a reserved config value. It is not implemented as a local provider adapter yet.
|
|
@@ -245,7 +249,7 @@ secrets: [],
|
|
|
245
249
|
|
|
246
250
|
`test/fake` is deterministic. It is useful for scaffold checks, direct tool checks, and fake-provider evals, but it does not validate natural conversation quality.
|
|
247
251
|
|
|
248
|
-
Before claiming real conversation behavior has been tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, or another supported provider. Do not choose for them. After the owner chooses, update `agentkit.config.ts`, `.env.schema`, local secrets, hosted secrets if deploying, then rerun chat/UI checks.
|
|
252
|
+
Before claiming real conversation behavior has been tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, OpenCode Zen, OpenCode Go, or another supported provider. Do not choose for them. After the owner chooses, update `agentkit.config.ts`, `.env.schema`, local secrets, hosted secrets if deploying, then rerun chat/UI checks.
|
|
249
253
|
|
|
250
254
|
OpenAI example:
|
|
251
255
|
|
|
@@ -270,6 +274,30 @@ If a provider key is missing, the runtime returns `secret_not_found`.
|
|
|
270
274
|
|
|
271
275
|
For OpenRouter, prefer model ids or aliases known to the installed Pi SDK, such as `~google/gemini-flash-latest`. If an OpenRouter id is newer than Pi's registry, AgentKit passes the raw id through to OpenRouter with conservative unknown-model metadata. OpenRouter can still reject invalid, inaccessible, or unsupported models, and unknown-model cost/capability metadata is not authoritative.
|
|
272
276
|
|
|
277
|
+
OpenCode Zen example:
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
provider: {
|
|
281
|
+
name: "opencode",
|
|
282
|
+
model: "big-pickle",
|
|
283
|
+
},
|
|
284
|
+
secrets: ["OPENCODE_API_KEY"],
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Use an OpenCode Zen model id listed by the installed Pi SDK, such as `big-pickle`, `deepseek-v4-flash-free`, `claude-sonnet-4-5`, or `gpt-5.4-mini`.
|
|
288
|
+
|
|
289
|
+
OpenCode Go example:
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
provider: {
|
|
293
|
+
name: "opencode-go",
|
|
294
|
+
model: "deepseek-v4-flash",
|
|
295
|
+
},
|
|
296
|
+
secrets: ["OPENCODE_API_KEY"],
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Use an OpenCode Go model id listed by the installed Pi SDK, such as `deepseek-v4-flash`, `deepseek-v4-pro`, `glm-5.1`, `kimi-k2.6`, `minimax-m2.7`, or `qwen3.6-plus`.
|
|
300
|
+
|
|
273
301
|
## Knowledge Contract
|
|
274
302
|
|
|
275
303
|
Knowledge is AgentKit's native retrieval layer for facts the agent should ground in source files. Use it for FAQs, prices, policies, service descriptions, procedures, CSV tables, and reference docs. Do not put secrets, credentials, `.env` contents, or live customer/payment records in Knowledge. Use tools for live or authorization-sensitive data.
|
|
@@ -602,7 +630,7 @@ CREATE TABLE IF NOT EXISTS appointments (
|
|
|
602
630
|
);
|
|
603
631
|
```
|
|
604
632
|
|
|
605
|
-
`schema.sql` is an idempotent bootstrap file
|
|
633
|
+
`schema.sql` is an idempotent bootstrap file. Use `CREATE TABLE IF NOT EXISTS`, `CREATE INDEX IF NOT EXISTS`, and only safe additive `ALTER TABLE` statements. Use ordered `migrations/*.sql` for production-shaped schema evolution; `agentkit db migrate` applies unapplied local migrations before `schema.sql`.
|
|
606
634
|
|
|
607
635
|
Example tool:
|
|
608
636
|
|
|
@@ -831,7 +859,7 @@ tools.order
|
|
|
831
859
|
tools.persisted
|
|
832
860
|
```
|
|
833
861
|
|
|
834
|
-
Import `defineEval` from `@andreprado/agentkit` when writing new evals. `tools.persisted` validates the tool call saved in local SQLite `tool_calls`, not a provider-specific raw response shape. It can be a tool name string or an object with `name`, `input`, `output`, `rendered`, `status`, and/or `visibility`. `tool_call` and `persisted_tool_call` remain accepted as backwards-compatible aliases, but new evals should use `tools.persisted`.
|
|
862
|
+
Import `defineEval` from `@andreprado/agentkit` when writing new evals. `tools.persisted` validates the tool call saved in the eval run's local SQLite `tool_calls`, not a provider-specific raw response shape. It can be a tool name string or an object with `name`, `input`, `output`, `rendered`, `status`, and/or `visibility`. `tool_call` and `persisted_tool_call` remain accepted as backwards-compatible aliases, but new evals should use `tools.persisted`.
|
|
835
863
|
|
|
836
864
|
For date-sensitive evals, set top-level `now` to an ISO timestamp with an explicit timezone designator such as `Z` or `-05:00`. AgentKit uses that fixed clock for every turn and tool call in the eval so "today", "tomorrow", and weekdays remain deterministic while normal chat continues to use the real current date.
|
|
837
865
|
|
|
@@ -939,7 +967,7 @@ agentkit deploy smoke --message "hello"
|
|
|
939
967
|
agentkit chat-ui --deploy
|
|
940
968
|
```
|
|
941
969
|
|
|
942
|
-
`agentkit deploy doctor` checks AgentKit Cloud login, hosted deploy entitlement, online deploy capacity, hosted secrets, local `.env` names that still need `agentkit secret set`, managed Composio API/auth-config readiness by toolkit, and private-access runtime token handling. `agentkit deploy` sends the capsule to AgentKit Cloud, runs the same readiness check automatically before building and uploading, updates the current project deploy slot by default,
|
|
970
|
+
`agentkit deploy doctor` checks AgentKit Cloud login, hosted deploy entitlement, online deploy capacity, hosted secrets, local `.env` names that still need `agentkit secret set`, managed Composio API/auth-config readiness by toolkit, and private-access runtime token handling. `agentkit deploy` sends the capsule to AgentKit Cloud, runs the same readiness check automatically before building and uploading, updates the current project deploy slot by default, writes the local chat/UI deploy access token to `.agentkit/chat-access-token.json`, and prints a production handoff with URL, UI command, secret status, database/schema artifact, integration connect commands, smoke status, and the next recommended command. `agentkit deploy --smoke "hello"` deploys and then tests `/v1/chat` with the deploy access token. `agentkit deploy smoke --message "hello"` repeats that smoke against the last local deploy. `agentkit chat-ui --deploy` serves a local UI pointed at the hosted deploy using that token without exposing it to browser code, shows the conversation id and tool calls, and supports starting a new conversation. Use `agentkit conversations trace <conversation-id> --deploy` to pull hosted conversation messages and tool calls from the last deploy. Production deploys require an account with `cloudflare_deploy_alpha` or purchased/manual deploy slots; local commands and dry-run builds do not require login. AgentKit owns infrastructure selection, backend migration, managed secrets, and public URL creation.
|
|
943
971
|
|
|
944
972
|
The CLI defaults to the hosted AgentKit Cloud API at `https://agentkit-cloud.aibuilders.com.br`. Use `AGENTKIT_CLOUD_API_URL` or `agentkit deploy --api <url>` only when the owner gives you a non-default AgentKit Cloud API URL.
|
|
945
973
|
|
package/docs/llms.txt
CHANGED
|
@@ -95,16 +95,18 @@ agentkit open
|
|
|
95
95
|
|
|
96
96
|
On Windows PowerShell, if `npm.ps1` or `npx.ps1` is blocked with `PSSecurityException`, run capsule scripts through the `.cmd` shims, for example `npm.cmd run agentkit -- inspect`, `npm.cmd run agentkit -- knowledge sync`, or `npm.cmd run eval`.
|
|
97
97
|
|
|
98
|
-
Generated capsules include `AGENTKIT.md`, `AGENTS.md`, and a repo-local `skills/` pack so Codex, Claude Code, or another coding agent can treat the owner's natural-language request as the brief and start building immediately without loading the full contract by default. Start with `skills/agentkit-capsule/SKILL.md`, then load the task skill for the current work. `agentkit handoff codex "Develop an ophthalmology office intake agent"` is an optional prompt-printing shortcut for users who are not already inside a coding-agent workspace. There is no wizard
|
|
98
|
+
Generated capsules include `AGENTKIT.md`, `AGENTS.md`, and a repo-local `skills/` pack so Codex, Claude Code, or another coding agent can treat the owner's natural-language request as the brief and start building immediately without loading the full contract by default. Start with `skills/agentkit-capsule/SKILL.md`, then load the task skill for the current work. `agentkit handoff codex "Develop an ophthalmology office intake agent"` is an optional prompt-printing shortcut for users who are not already inside a coding-agent workspace. There is no AgentKit CLI wizard in the normal flow: the coding agent edits the capsule directly from the scaffold and contract.
|
|
99
99
|
|
|
100
100
|
UI testing is part of the handoff. For local UI testing, run `agentkit dev`, open the printed `Chat:` URL, and tell the owner the exact URL. After hosted deploy, run `agentkit chat-ui --deploy`, open the printed `Chat:` URL, and tell the owner it is connected to the deploy.
|
|
101
101
|
|
|
102
102
|
Hosted Chat UI shows the current conversation id, tool calls, tool errors, and a new-conversation control. Use `agentkit conversations trace <conversation-id> --deploy` to pull the hosted trace from the last deploy.
|
|
103
103
|
|
|
104
|
-
`test/fake` is deterministic and validates scaffold, direct tool calls, and fake-provider evals. It does not validate natural conversation quality. Before claiming real conversation behavior has been tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, or another supported provider. Do not choose for them.
|
|
104
|
+
`test/fake` is deterministic and validates scaffold, direct tool calls, and fake-provider evals. It does not validate natural conversation quality. Before claiming real conversation behavior has been tested, ask the owner which provider to use: OpenRouter, OpenAI, Anthropic, OpenCode Zen, OpenCode Go, or another supported provider. Do not choose for them.
|
|
105
105
|
|
|
106
106
|
For OpenRouter, prefer model ids or aliases known to the installed Pi SDK, such as `~google/gemini-flash-latest`. If an OpenRouter id is newer than Pi's registry, AgentKit passes the raw id through to OpenRouter with conservative unknown-model metadata; OpenRouter can still reject invalid, inaccessible, or unsupported models.
|
|
107
107
|
|
|
108
|
+
For OpenCode Zen, use `provider: { name: "opencode", model: "big-pickle" }`. For OpenCode Go, use `provider: { name: "opencode-go", model: "deepseek-v4-flash" }`. Both use `OPENCODE_API_KEY` in `secrets` and `.env.schema`.
|
|
109
|
+
|
|
108
110
|
AgentKit injects the current ISO timestamp, local date, weekday, local date/time, and timezone dynamically into every chat run. Set `timeZone` in `agentkit.config.ts` for scheduling agents so "today", "tomorrow", and weekdays resolve in the business/user timezone; otherwise AgentKit falls back to `AGENTKIT_TIME_ZONE`, valid `TZ`, then the runtime default. Do not hardcode today's date in prompts.
|
|
109
111
|
|
|
110
112
|
Current local endpoints from `agentkit dev`:
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
|
+
import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http";
|
|
3
3
|
import { join, relative, resolve } from "node:path";
|
|
4
4
|
|
|
5
5
|
import { findAgentCapsuleRoot } from "../runtime/config";
|
|
@@ -9,8 +9,15 @@ import { defaultDeployChatAccessTokenName, defaultDeployChatAccessTokenPath } fr
|
|
|
9
9
|
|
|
10
10
|
export async function startDeployChatUiServer(
|
|
11
11
|
cwd: string,
|
|
12
|
-
options: { port: number; tokenFile?: string },
|
|
13
|
-
): Promise<{
|
|
12
|
+
options: { port: number; tokenFile?: string; autoPort?: boolean },
|
|
13
|
+
): Promise<{
|
|
14
|
+
url: string;
|
|
15
|
+
deployUrl: string;
|
|
16
|
+
tokenSource: string;
|
|
17
|
+
port: number;
|
|
18
|
+
portConflict: { port: number } | null;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
}> {
|
|
14
21
|
const root = await findAgentCapsuleRoot(cwd);
|
|
15
22
|
const state = await readLocalDeployStateIfExists(root);
|
|
16
23
|
|
|
@@ -23,9 +30,37 @@ export async function startDeployChatUiServer(
|
|
|
23
30
|
: join(root, defaultDeployChatAccessTokenPath);
|
|
24
31
|
const hostname = "localhost";
|
|
25
32
|
const deployUrl = state.url;
|
|
33
|
+
const start = await listenForDeployChatUiServer({
|
|
34
|
+
hostname,
|
|
35
|
+
requestedPort: options.port,
|
|
36
|
+
autoPort: options.autoPort === true,
|
|
37
|
+
create: () => createDeployChatUiHttpServer({ root, tokenPath, hostname, requestedPort: options.port, deployUrl }),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
url: `http://${hostname}:${start.port}`,
|
|
42
|
+
deployUrl,
|
|
43
|
+
tokenSource: process.env.AGENTKIT_DEPLOY_ACCESS_TOKEN ? "AGENTKIT_DEPLOY_ACCESS_TOKEN" : relativePath(root, tokenPath),
|
|
44
|
+
port: start.port,
|
|
45
|
+
portConflict: start.portConflict,
|
|
46
|
+
stop: () =>
|
|
47
|
+
new Promise<void>((resolvePromise, reject) => {
|
|
48
|
+
start.server.close((error) => (error ? reject(error) : resolvePromise()));
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function createDeployChatUiHttpServer(input: {
|
|
54
|
+
root: string;
|
|
55
|
+
tokenPath: string;
|
|
56
|
+
hostname: string;
|
|
57
|
+
requestedPort: number;
|
|
58
|
+
deployUrl: string;
|
|
59
|
+
}): Server {
|
|
60
|
+
const { root, tokenPath, hostname, requestedPort, deployUrl } = input;
|
|
26
61
|
const server = createServer(async (request, response) => {
|
|
27
62
|
try {
|
|
28
|
-
const requestUrl = new URL(request.url ?? "/", `http://${request.headers.host ?? `${hostname}:${
|
|
63
|
+
const requestUrl = new URL(request.url ?? "/", `http://${request.headers.host ?? `${hostname}:${requestedPort}`}`);
|
|
29
64
|
|
|
30
65
|
if (request.method === "GET" && requestUrl.pathname === "/") {
|
|
31
66
|
sendHtml(response, renderDeployChatUi({ deployUrl }));
|
|
@@ -102,23 +137,59 @@ export async function startDeployChatUiServer(
|
|
|
102
137
|
}
|
|
103
138
|
});
|
|
104
139
|
|
|
105
|
-
|
|
140
|
+
return server;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function listenForDeployChatUiServer(input: {
|
|
144
|
+
hostname: string;
|
|
145
|
+
requestedPort: number;
|
|
146
|
+
autoPort: boolean;
|
|
147
|
+
create: () => Server;
|
|
148
|
+
}): Promise<{ server: Server; port: number; portConflict: { port: number } | null }> {
|
|
149
|
+
let firstConflict: { port: number } | null = null;
|
|
150
|
+
const lastPort = input.autoPort ? input.requestedPort + 50 : input.requestedPort;
|
|
151
|
+
|
|
152
|
+
for (let port = input.requestedPort; port <= lastPort; port += 1) {
|
|
153
|
+
const server = input.create();
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
await listen(server, input.hostname, port);
|
|
157
|
+
return { server, port, portConflict: port === input.requestedPort ? null : firstConflict };
|
|
158
|
+
} catch (error) {
|
|
159
|
+
await closeServerAfterListenError(server);
|
|
160
|
+
|
|
161
|
+
if (!input.autoPort || !isAddressInUseError(error)) {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
firstConflict ??= { port };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
throw new AgentKitError(
|
|
170
|
+
"runtime_error",
|
|
171
|
+
`Could not allocate a local AgentKit hosted chat UI port after ${input.requestedPort}-${lastPort}.`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function listen(server: Server, hostname: string, port: number): Promise<void> {
|
|
176
|
+
return new Promise((resolvePromise, reject) => {
|
|
106
177
|
server.once("error", reject);
|
|
107
|
-
server.listen(
|
|
178
|
+
server.listen(port, hostname, () => {
|
|
108
179
|
server.off("error", reject);
|
|
109
180
|
resolvePromise();
|
|
110
181
|
});
|
|
111
182
|
});
|
|
183
|
+
}
|
|
112
184
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
};
|
|
185
|
+
async function closeServerAfterListenError(server: Server): Promise<void> {
|
|
186
|
+
await new Promise<void>((resolvePromise) => {
|
|
187
|
+
server.close(() => resolvePromise());
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function isAddressInUseError(error: unknown): boolean {
|
|
192
|
+
return Boolean(error && typeof error === "object" && "code" in error && error.code === "EADDRINUSE");
|
|
122
193
|
}
|
|
123
194
|
|
|
124
195
|
export async function readDeployAccessTokenForUi(tokenPath: string): Promise<string> {
|
|
@@ -29,6 +29,16 @@ type DeployReadinessReport = {
|
|
|
29
29
|
apiUrl: string;
|
|
30
30
|
context: DeployReadinessContext;
|
|
31
31
|
checks: DeployReadinessCheck[];
|
|
32
|
+
cloudAuth: {
|
|
33
|
+
source?: string;
|
|
34
|
+
accountEmail?: string;
|
|
35
|
+
};
|
|
36
|
+
onlineCapacity: {
|
|
37
|
+
accountUsed?: number;
|
|
38
|
+
accountLimit?: number;
|
|
39
|
+
globalUsed?: number;
|
|
40
|
+
globalLimit?: number;
|
|
41
|
+
};
|
|
32
42
|
};
|
|
33
43
|
|
|
34
44
|
export async function checkDeployReadiness(options: {
|
|
@@ -39,6 +49,12 @@ export async function checkDeployReadiness(options: {
|
|
|
39
49
|
const auth = options.requireLogin ? await readCloudAuthForApiUrl(options.apiUrl) : null;
|
|
40
50
|
const checks: DeployReadinessCheck[] = [];
|
|
41
51
|
let cloudAuthUsable = false;
|
|
52
|
+
const cloudAuth: DeployReadinessReport["cloudAuth"] = {};
|
|
53
|
+
const onlineCapacity: DeployReadinessReport["onlineCapacity"] = {};
|
|
54
|
+
|
|
55
|
+
if (auth?.token) {
|
|
56
|
+
cloudAuth.source = formatCloudAuthSource(auth);
|
|
57
|
+
}
|
|
42
58
|
|
|
43
59
|
if (context.runtime !== "edge") {
|
|
44
60
|
checks.push({
|
|
@@ -84,6 +100,9 @@ export async function checkDeployReadiness(options: {
|
|
|
84
100
|
try {
|
|
85
101
|
const me = (await cloudApiRequest(options.apiUrl, "/v1/me", { method: "GET" })) as CloudMeResponse;
|
|
86
102
|
const email = me.account?.email;
|
|
103
|
+
if (email) {
|
|
104
|
+
cloudAuth.accountEmail = email;
|
|
105
|
+
}
|
|
87
106
|
checks.push({
|
|
88
107
|
status: "pass",
|
|
89
108
|
title: "Login",
|
|
@@ -164,6 +183,22 @@ export async function checkDeployReadiness(options: {
|
|
|
164
183
|
const globalLimit = normalizeOptionalNumber(global?.limit);
|
|
165
184
|
const globalUsed = normalizeOptionalNumber(global?.used);
|
|
166
185
|
|
|
186
|
+
if (accountLimit !== undefined) {
|
|
187
|
+
onlineCapacity.accountLimit = accountLimit;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (accountUsed !== undefined) {
|
|
191
|
+
onlineCapacity.accountUsed = accountUsed;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (globalLimit !== undefined) {
|
|
195
|
+
onlineCapacity.globalLimit = globalLimit;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (globalUsed !== undefined) {
|
|
199
|
+
onlineCapacity.globalUsed = globalUsed;
|
|
200
|
+
}
|
|
201
|
+
|
|
167
202
|
if (accountLimit !== undefined && accountUsed !== undefined && accountUsed >= accountLimit) {
|
|
168
203
|
checks.push({
|
|
169
204
|
status: "fail",
|
|
@@ -374,6 +409,8 @@ export async function checkDeployReadiness(options: {
|
|
|
374
409
|
apiUrl: options.apiUrl,
|
|
375
410
|
context,
|
|
376
411
|
checks,
|
|
412
|
+
cloudAuth,
|
|
413
|
+
onlineCapacity,
|
|
377
414
|
};
|
|
378
415
|
}
|
|
379
416
|
|
|
@@ -383,6 +420,19 @@ export function printDeployReadinessReport(report: DeployReadinessReport): void
|
|
|
383
420
|
console.log(`Project ID: ${report.context.projectId}`);
|
|
384
421
|
console.log(`Target: ${report.context.target}`);
|
|
385
422
|
console.log(`API: ${report.apiUrl}`);
|
|
423
|
+
const authSummary = formatDeployCloudAuthSummary(report);
|
|
424
|
+
|
|
425
|
+
if (authSummary) {
|
|
426
|
+
console.log(`Account: ${authSummary.account}`);
|
|
427
|
+
console.log(`Auth source: ${authSummary.source}`);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const capacitySummary = formatDeployOnlineCapacity(report, "current");
|
|
431
|
+
|
|
432
|
+
if (capacitySummary) {
|
|
433
|
+
console.log(`Capacity: ${capacitySummary}`);
|
|
434
|
+
}
|
|
435
|
+
|
|
386
436
|
console.log("");
|
|
387
437
|
|
|
388
438
|
for (const check of report.checks) {
|
|
@@ -394,6 +444,36 @@ export function printDeployReadinessReport(report: DeployReadinessReport): void
|
|
|
394
444
|
}
|
|
395
445
|
}
|
|
396
446
|
|
|
447
|
+
export function formatDeployCloudAuthSummary(
|
|
448
|
+
report: DeployReadinessReport,
|
|
449
|
+
): { account: string; source: string } | null {
|
|
450
|
+
if (!report.cloudAuth.accountEmail || !report.cloudAuth.source) {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
account: report.cloudAuth.accountEmail,
|
|
456
|
+
source: report.cloudAuth.source,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export function formatDeployOnlineCapacity(
|
|
461
|
+
report: DeployReadinessReport,
|
|
462
|
+
timing: "current" | "before deploy",
|
|
463
|
+
): string | null {
|
|
464
|
+
const suffix = timing === "before deploy" ? " before deploy" : "";
|
|
465
|
+
|
|
466
|
+
if (report.onlineCapacity.accountUsed !== undefined && report.onlineCapacity.accountLimit !== undefined) {
|
|
467
|
+
return `${report.onlineCapacity.accountUsed}/${report.onlineCapacity.accountLimit} account online deploy slots in use${suffix}`;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (report.onlineCapacity.globalUsed !== undefined && report.onlineCapacity.globalLimit !== undefined) {
|
|
471
|
+
return `${report.onlineCapacity.globalUsed}/${report.onlineCapacity.globalLimit} global online deploy slots in use${suffix}`;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
|
|
397
477
|
export async function syncHostedSecretsFromLocal(options: { apiUrl: string; projectId: string }): Promise<void> {
|
|
398
478
|
const context = await loadDeployReadinessContext(process.cwd(), process.env);
|
|
399
479
|
const localEnv = await loadCapsuleEnv(context.root, {});
|