@andreprado/agentkit 0.1.0-alpha.24 → 0.1.0-alpha.26

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 (34) hide show
  1. package/README.md +4 -1
  2. package/docs/guides/add-managed-composio.md +2 -2
  3. package/docs/guides/add-tool.md +4 -0
  4. package/docs/guides/channel-security.md +2 -0
  5. package/docs/guides/connect-whatsapp-uazapi.md +32 -19
  6. package/docs/guides/connect-whatsapp-zapster.md +35 -20
  7. package/docs/guides/create-agent.md +12 -0
  8. package/docs/guides/prepare-deploy.md +1 -1
  9. package/docs/guides/security-rules.md +3 -0
  10. package/docs/guides/use-jev.md +67 -0
  11. package/docs/llms-full.txt +17 -5
  12. package/docs/llms.txt +8 -2
  13. package/package.json +3 -4
  14. package/src/cli/commands/channels.ts +2 -2
  15. package/src/cli/help.ts +5 -3
  16. package/src/cli/index.ts +2 -5
  17. package/src/cli/new-command.ts +41 -0
  18. package/src/index.ts +2 -2
  19. package/src/runtime/channels/whatsapp-uazapi.ts +8 -12
  20. package/src/runtime/channels/whatsapp-zapster.ts +11 -14
  21. package/src/runtime/config.ts +2 -2
  22. package/src/runtime/dev-server.ts +74 -10
  23. package/src/runtime/integrations/composio.ts +3 -1
  24. package/src/runtime/targets/cloudflare/build.ts +20 -2
  25. package/src/runtime/tools.ts +18 -0
  26. package/src/templates/skills/agentkit-build-agent/SKILL.md +2 -2
  27. package/src/templates/skills/agentkit-capsule/SKILL.md +2 -2
  28. package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +5 -12
  29. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +6 -12
  30. package/src/templates/skills/agentkit-integrations/SKILL.md +1 -1
  31. package/src/templates/skills/agentkit-security/SKILL.md +2 -0
  32. package/src/templates/skills/agentkit-tools/SKILL.md +5 -1
  33. package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +8 -8
  34. package/src/templates/skills/agentkit-tools/examples/jev-service-fit.tool.md +110 -0
package/README.md CHANGED
@@ -24,12 +24,15 @@ Generated capsules use the built-in `test/fake` provider by default, so the firs
24
24
  ## What To Know First
25
25
 
26
26
  ```sh
27
- agentkit new <name> [--template blank|support|dentista] [--no-install]
27
+ agentkit new [name] [--template blank|support|dentista] [--no-install]
28
+ agentkit new .
28
29
  agentkit dev
29
30
  agentkit chat --message <text> [--conversation-id <id>]
30
31
  agentkit inspect
31
32
  ```
32
33
 
34
+ Run `agentkit new` without a name in an interactive terminal to be prompted for the project folder. Use `agentkit new .` to create the capsule in the current directory.
35
+
33
36
  Once the capsule is running:
34
37
 
35
38
  ```sh
@@ -114,9 +114,9 @@ googlecalendar: [
114
114
 
115
115
  ## Write Confirmation
116
116
 
117
- Managed Composio requires confirmation for external write actions by default. For actions such as create, update, delete, send, patch, move, insert, clear, remove, import, or quick add, the generated `agentkit_composio_execute` tool requires `confirmed: true`.
117
+ Managed Composio requires operator invocation for external write actions. If an integration allows create, update, delete, send, patch, move, insert, clear, remove, import, or quick-add actions, AgentKit blocks that generated tool during model-driven chat, channel, and eval runs. Review the exact action and invoke `agentkit_composio_execute` directly with `agentkit tool`; write actions also require `confirmed: true` by default.
118
118
 
119
- Set `confirmed: true` only after the user confirms the exact external change. If a capsule intentionally handles confirmation elsewhere, disable this guard explicitly:
119
+ `confirmExternalWrites: false` disables only Composio's secondary `confirmed` input check. It does not bypass AgentKit's operator-only permission boundary:
120
120
 
121
121
  ```ts
122
122
  composioManaged({
@@ -8,6 +8,8 @@ Add a TypeScript tool to an Agent Capsule, register it in `agentkit.config.ts`,
8
8
 
9
9
  Use this when the agent needs to call code, read an API, query a database, or perform a small action behind a typed contract.
10
10
 
11
+ For requests such as “use Jev to qualify leads” or “use TypeSafe to rank candidates,” follow [Use Jev](use-jev.md) and adapt the bundled tool example to the requested behavior.
12
+
11
13
  ## Commands
12
14
 
13
15
  From a capsule root:
@@ -265,6 +267,8 @@ Use it for diagnostics only, not for bypassing AgentKit runtime services or choo
265
267
  - Do not read arbitrary `process.env` inside tools.
266
268
  - Use `ctx.secrets.SECRET_NAME`.
267
269
  - Set `timeoutMs` for slow external calls.
270
+ - End read-only permissions with `:read`, for example `crm:contacts:read`.
271
+ - Declare writes, sends, deletes, payments, or broad external calls with a non-read permission such as `email:send`. AgentKit blocks those permissions during model-driven chat, channel, and eval runs; the local operator must review and invoke the exact call with `agentkit tool`.
268
272
  - Set `visibility: "internal"` for operational outputs such as classifications, scores, routing labels, fraud decisions, or other fields the agent should persist but not reveal literally to the user.
269
273
  - Do not log secret values.
270
274
 
@@ -38,6 +38,8 @@ agentkit channels deliveries show <delivery-id>
38
38
  - Keep generic output webhook URLs on public HTTPS origins. AgentKit rejects localhost, private network, link-local, and metadata-service hosts before sending.
39
39
  - Do not route replies to a channel name from the inbound payload. `replyTo.channel` must be static config, and `recipientFrom` may only select the recipient identifier.
40
40
  - Do not remove `EVOLUTION_WEBHOOK_TOKEN` from Evolution WhatsApp webhooks. Evolution provider docs expose webhook delivery setup but no webhook signing-secret contract, so AgentKit requires a secret token query parameter and rejects requests without it.
41
+ - Do not remove `UAZAPI_WEBHOOK_TOKEN` or `ZAPSTER_WEBHOOK_TOKEN`. These are AgentKit-owned URL secrets, not provider-issued tokens. The adapters require them because the providers' other webhook fields do not provide a strong shared-secret signature.
42
+ - A local HTTPS tunnel may forward only authenticated `/channels/.../webhook` routes to `agentkit dev`; the local chat, inspect, tools, files, and conversation APIs remain loopback-only.
41
43
  - Keep `EVOLUTION_API_BASE_URL` on a public HTTPS origin. AgentKit rejects localhost, private network, link-local, and metadata-service hosts for Evolution outbound and media-download requests.
42
44
  - Inspect delivery IDs, hashes, redacted metadata, and statuses instead of raw provider payloads.
43
45
  - Keep channel plumbing out of the agent's application database. The user's Turso tables are for the agent's business data.
@@ -2,21 +2,17 @@
2
2
 
3
3
  ## Goal
4
4
 
5
- Connect a UAZAPI WhatsApp instance to a hosted AgentKit WhatsApp channel.
5
+ Connect a UAZAPI WhatsApp instance to an AgentKit WhatsApp channel locally or when hosted.
6
6
 
7
7
  ## When To Use It
8
8
 
9
- Use this after `whatsappChannel({ name: "support-whatsapp", provider: "uazapi" })` exists in `agentkit.config.ts` and the capsule has been deployed.
9
+ Use this after `whatsappChannel({ name: "support-whatsapp", provider: "uazapi" })` exists in `agentkit.config.ts`.
10
10
 
11
11
  ## Commands
12
12
 
13
13
  ```sh
14
- agentkit deploy
15
- agentkit channels connect whatsapp support-whatsapp --provider uazapi
16
- agentkit channels status support-whatsapp
17
- agentkit channels test support-whatsapp --message "hello"
18
- agentkit channels deliveries list support-whatsapp
19
- agentkit channels buffers list support-whatsapp
14
+ node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('hex'))" | agentkit env set UAZAPI_WEBHOOK_TOKEN --stdin
15
+ agentkit dev
20
16
  ```
21
17
 
22
18
  Required secrets:
@@ -24,11 +20,6 @@ Required secrets:
24
20
  ```txt
25
21
  UAZAPI_BASE_URL
26
22
  UAZAPI_TOKEN
27
- ```
28
-
29
- Optional hardening secret:
30
-
31
- ```txt
32
23
  UAZAPI_WEBHOOK_TOKEN
33
24
  ```
34
25
 
@@ -52,7 +43,28 @@ export default defineAgent({
52
43
  });
53
44
  ```
54
45
 
55
- ## Setup Behavior
46
+ ## Local Usage
47
+
48
+ `UAZAPI_WEBHOOK_TOKEN` is an AgentKit-owned secret, not a token issued by UAZAPI. Generate a different value for every channel and keep it in the ignored local `.env`:
49
+
50
+ ```sh
51
+ node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('hex'))" | npm run agentkit -- env set UAZAPI_WEBHOOK_TOKEN --stdin
52
+ npm run agentkit -- env set UAZAPI_BASE_URL --stdin
53
+ npm run agentkit -- env set UAZAPI_TOKEN --stdin
54
+ npm run agentkit -- dev
55
+ ```
56
+
57
+ Expose the printed local port through an HTTPS tunnel, then register this exact URL with UAZAPI:
58
+
59
+ ```txt
60
+ https://<tunnel-host>/channels/support-whatsapp/whatsapp/uazapi/webhook?token=<UAZAPI_WEBHOOK_TOKEN>
61
+ ```
62
+
63
+ Configure UAZAPI with `addUrlEvents: false` and `addUrlTypesMessages: false` so it calls that exact URL. AgentKit allows a public tunnel host only on authenticated channel webhook paths; local chat, inspect, tools, files, and conversation APIs remain loopback-only.
64
+
65
+ Send a real WhatsApp message after registration. A `200` response proves UAZAPI preserved the tokenized URL and AgentKit accepted it. A `channel_signature_invalid` response means the configured URL omitted, changed, or stripped the token. If the tunnel hostname changes, update the registered webhook URL.
66
+
67
+ ## Hosted Setup Behavior
56
68
 
57
69
  `agentkit channels connect whatsapp support-whatsapp --provider uazapi` creates or updates the hosted channel, verifies managed secrets, calls UAZAPI `/webhook`, confirms the configured webhook is listed by UAZAPI, then runs a synthetic inbound smoke.
58
70
 
@@ -62,7 +74,7 @@ Expected webhook URL shape:
62
74
  https://<deploy-host>/channels/support-whatsapp/whatsapp/uazapi/webhook
63
75
  ```
64
76
 
65
- If the channel declares `UAZAPI_WEBHOOK_TOKEN`, AgentKit registers the webhook URL with the token query parameter:
77
+ AgentKit requires `UAZAPI_WEBHOOK_TOKEN` and registers the webhook URL with the token query parameter:
66
78
 
67
79
  ```txt
68
80
  https://<deploy-host>/channels/support-whatsapp/whatsapp/uazapi/webhook?token=<UAZAPI_WEBHOOK_TOKEN>
@@ -90,8 +102,9 @@ UAZAPI audio webhooks become normalized audio messages. The retryable channel wo
90
102
 
91
103
  - Keep phone numbers redacted in logs by default.
92
104
  - Do not store UAZAPI tokens in `agentkit.config.ts`.
93
- - Use optional `UAZAPI_WEBHOOK_TOKEN` when the endpoint should require a secret query token in addition to the public route.
94
- - UAZAPI does not expose a documented webhook body-signature contract in AgentKit V1; treat the optional query token as the hardening layer.
105
+ - Keep `UAZAPI_WEBHOOK_TOKEN` configured. UAZAPI V1 has no body-signature contract, so AgentKit rejects webhooks without the secret query token.
106
+ - UAZAPI does not expose a documented webhook body-signature contract in AgentKit V1; the AgentKit-owned query token is the authentication layer.
107
+ - Treat the complete tokenized URL as a secret and rotate `UAZAPI_WEBHOOK_TOKEN` if it appears in logs or screenshots.
95
108
  - AgentKit ignores `fromMe` and `wasSentByApi` messages to avoid reply loops.
96
109
  - Text replies call UAZAPI `POST /send/text` with the `token` header and a body containing `number`, `text`, `readchat`, `async`, `track_source`, and `track_id`.
97
110
  - Real provider success is recorded as `provider_sent` only when UAZAPI returns a provider message id.
@@ -111,10 +124,10 @@ agentkit channels deliveries show <delivery-id>
111
124
  ## Troubleshooting
112
125
 
113
126
  `channel_secret_missing`:
114
- Set `UAZAPI_BASE_URL` and `UAZAPI_TOKEN` as hosted managed secrets. If the channel declares `UAZAPI_WEBHOOK_TOKEN`, set that managed secret too.
127
+ Set `UAZAPI_BASE_URL`, `UAZAPI_TOKEN`, and `UAZAPI_WEBHOOK_TOKEN` as secrets.
115
128
 
116
129
  `channel_signature_invalid`:
117
- The optional UAZAPI webhook query token does not match.
130
+ The required UAZAPI webhook query token does not match.
118
131
 
119
132
  `channel_provider_setup_invalid`:
120
133
  `UAZAPI_BASE_URL` is not an allowed HTTPS public base URL.
@@ -2,21 +2,17 @@
2
2
 
3
3
  ## Goal
4
4
 
5
- Connect a Zapster WhatsApp account to a hosted AgentKit WhatsApp channel.
5
+ Connect a Zapster WhatsApp account to an AgentKit WhatsApp channel locally or when hosted.
6
6
 
7
7
  ## When To Use It
8
8
 
9
- Use this after `whatsappChannel({ name: "support-whatsapp", provider: "zapster" })` exists in `agentkit.config.ts` and the capsule has been deployed.
9
+ Use this after `whatsappChannel({ name: "support-whatsapp", provider: "zapster" })` exists in `agentkit.config.ts`.
10
10
 
11
11
  ## Commands
12
12
 
13
13
  ```sh
14
- agentkit deploy
15
- agentkit channels connect whatsapp support-whatsapp --provider zapster
16
- agentkit channels status support-whatsapp
17
- agentkit channels test support-whatsapp --message "hello"
18
- agentkit channels deliveries list support-whatsapp --since 24h
19
- agentkit channels buffers list support-whatsapp
14
+ node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('hex'))" | agentkit env set ZAPSTER_WEBHOOK_TOKEN --stdin
15
+ agentkit dev
20
16
  ```
21
17
 
22
18
  Required secrets:
@@ -25,11 +21,6 @@ Required secrets:
25
21
  ZAPSTER_API_KEY
26
22
  ZAPSTER_INSTANCE_ID
27
23
  ZAPSTER_WEBHOOK_ID
28
- ```
29
-
30
- Optional hardening secret:
31
-
32
- ```txt
33
24
  ZAPSTER_WEBHOOK_TOKEN
34
25
  ```
35
26
 
@@ -48,7 +39,8 @@ GROQ_API_KEY
48
39
  ## Files Created Or Edited
49
40
 
50
41
  - `agentkit.config.ts`: `whatsappChannel({ name: "support-whatsapp", provider: "zapster" })`.
51
- - `.agentkit/deploy.json`: deploy state for resolving the hosted deploy.
42
+ - `.env`: ignored local provider credentials and the AgentKit-owned webhook token.
43
+ - `.agentkit/deploy.json`: deploy state only when using the hosted workflow.
52
44
  - No user-managed webhook server.
53
45
 
54
46
  ## Minimal Working Example
@@ -69,6 +61,28 @@ export default defineAgent({
69
61
  });
70
62
  ```
71
63
 
64
+ ## Local Usage
65
+
66
+ `ZAPSTER_WEBHOOK_TOKEN` is an AgentKit-owned secret, not a token issued by Zapster. Generate a different value for every channel and keep it in the ignored local `.env`:
67
+
68
+ ```sh
69
+ node -e "process.stdout.write(require('node:crypto').randomBytes(32).toString('hex'))" | npm run agentkit -- env set ZAPSTER_WEBHOOK_TOKEN --stdin
70
+ npm run agentkit -- env set ZAPSTER_API_KEY --stdin
71
+ npm run agentkit -- env set ZAPSTER_INSTANCE_ID --stdin
72
+ npm run agentkit -- env set ZAPSTER_WEBHOOK_ID --stdin
73
+ npm run agentkit -- dev
74
+ ```
75
+
76
+ Expose the printed local port through an HTTPS tunnel, then register this exact URL with Zapster:
77
+
78
+ ```txt
79
+ https://<tunnel-host>/channels/support-whatsapp/whatsapp/zapster/webhook?token=<ZAPSTER_WEBHOOK_TOKEN>
80
+ ```
81
+
82
+ Zapster stores a complete webhook URL and sends `X-Instance-ID` and `X-Webhook-ID` with deliveries. AgentKit requires both expected IDs and the URL secret because those identifiers alone are not cryptographic authentication. AgentKit allows a public tunnel host only on authenticated channel webhook paths; local chat, inspect, tools, files, and conversation APIs remain loopback-only.
83
+
84
+ Send a real WhatsApp message after registration. A `200` response proves Zapster preserved the tokenized URL and AgentKit accepted it. A `channel_signature_invalid` response means the URL token or expected Zapster IDs did not match. If the tunnel hostname changes, update the registered webhook URL.
85
+
72
86
  To handle clients who send several WhatsApp messages before waiting, enable channel buffering:
73
87
 
74
88
  ```ts
@@ -123,7 +137,7 @@ export default defineAgent({
123
137
 
124
138
  Processing order:
125
139
 
126
- 1. AgentKit validates Zapster origin headers and the optional webhook token.
140
+ 1. AgentKit validates Zapster origin headers and the required webhook token.
127
141
  2. Zapster audio payloads become normalized audio messages.
128
142
  3. AgentKit records `audio_received` and enqueues a channel job before acknowledging Zapster.
129
143
  4. The retryable channel worker downloads the media URL from a trusted Zapster HTTPS host using `ZAPSTER_API_KEY`.
@@ -132,7 +146,7 @@ Processing order:
132
146
 
133
147
  Zapster payloads must include a media download URL such as `audio.downloadUrl`, `audio.url`, `audio.mediaUrl`, or the snake_case equivalents. The URL must be HTTPS and hosted by Zapster; AgentKit rejects arbitrary webhook-provided hosts before sending `ZAPSTER_API_KEY`. If Zapster sends only a media ID without a download URL, AgentKit records `channel_audio_download_unavailable` and does not create an agent run for that audio in V1.
134
148
 
135
- ## Setup Behavior
149
+ ## Hosted Setup Behavior
136
150
 
137
151
  `agentkit channels setup support-whatsapp` prints the stable AgentKit webhook URL. Paste it into Zapster webhook settings.
138
152
 
@@ -142,7 +156,7 @@ Expected webhook URL shape:
142
156
  https://<deploy-host>/channels/support-whatsapp/whatsapp/zapster/webhook
143
157
  ```
144
158
 
145
- If the channel declares `ZAPSTER_WEBHOOK_TOKEN`, register the Zapster URL with the token as a query parameter:
159
+ AgentKit requires `ZAPSTER_WEBHOOK_TOKEN`; register the Zapster URL with the token as a query parameter:
146
160
 
147
161
  ```txt
148
162
  https://<deploy-host>/channels/support-whatsapp/whatsapp/zapster/webhook?token=<ZAPSTER_WEBHOOK_TOKEN>
@@ -154,7 +168,8 @@ https://<deploy-host>/channels/support-whatsapp/whatsapp/zapster/webhook?token=<
154
168
  - Do not store Zapster API keys in `agentkit.config.ts`.
155
169
  - Inbound validation uses Zapster's `X-Instance-ID`, `X-Webhook-ID`, `X-Message-ID`, `X-Attempt-Count`, and `User-Agent: Zapsterapi/...` headers.
156
170
  - Zapster webhook headers are origin validation, not a cryptographic body signature.
157
- - Use optional `ZAPSTER_WEBHOOK_TOKEN` in the webhook URL when the endpoint should require an extra secret known only to AgentKit and Zapster.
171
+ - Keep `ZAPSTER_WEBHOOK_TOKEN` in the webhook URL. Zapster's metadata headers are not a shared-secret signature, so AgentKit rejects webhooks without the secret query token.
172
+ - Treat the complete tokenized URL as a secret and rotate `ZAPSTER_WEBHOOK_TOKEN` if it appears in logs or screenshots.
158
173
  - Unsupported media should be logged as skipped/unsupported without creating an agent run.
159
174
  - AgentKit handles Zapster `message.received` envelopes with event id at `id`, message text at `data.content.text`, and contact identity at `data.sender.id`.
160
175
  - Outbound replies call `POST https://api.zapsterapi.com/v1/wa/messages` with bearer auth and a JSON body containing `recipient`, `text`, and `instance_id`.
@@ -177,10 +192,10 @@ agentkit channels buffers retry support-whatsapp <conversation-id>
177
192
  ## Troubleshooting
178
193
 
179
194
  `channel_secret_missing`:
180
- Set `ZAPSTER_API_KEY`, `ZAPSTER_INSTANCE_ID`, and `ZAPSTER_WEBHOOK_ID` as hosted managed secrets. If the channel declares `ZAPSTER_WEBHOOK_TOKEN`, set that managed secret too.
195
+ Set `ZAPSTER_API_KEY`, `ZAPSTER_INSTANCE_ID`, `ZAPSTER_WEBHOOK_ID`, and `ZAPSTER_WEBHOOK_TOKEN` as secrets.
181
196
 
182
197
  `channel_signature_invalid`:
183
- Zapster is not sending the expected instance/webhook IDs, or the optional query token does not match.
198
+ Zapster is not sending the expected instance/webhook IDs, or the required query token does not match.
184
199
 
185
200
  `channel_unsupported_message_type` or skipped delivery:
186
201
  The inbound WhatsApp event was not supported text. Inspect the delivery record for provider metadata.
@@ -39,6 +39,18 @@ cd support-demo
39
39
  npm run agentkit -- tool lookup_order --input '{"orderId":"A100"}'
40
40
  ```
41
41
 
42
+ `agentkit new` can prompt for the project folder name when run in an interactive terminal:
43
+
44
+ ```sh
45
+ npx @andreprado/agentkit@alpha new
46
+ ```
47
+
48
+ Use `.` to create the capsule in the current directory:
49
+
50
+ ```sh
51
+ npx @andreprado/agentkit@alpha new . --template blank
52
+ ```
53
+
42
54
  ## Windows PowerShell
43
55
 
44
56
  If PowerShell blocks `npm.ps1` or `npx.ps1` with `PSSecurityException`, run the same commands through the Windows command shims:
@@ -166,7 +166,7 @@ No .agentkit committed
166
166
  All required secret names are declared
167
167
  Prompt path exists
168
168
  Tools have input schemas
169
- Dangerous tools have permissions
169
+ Read-only tools use `:read` permissions; dangerous tools use operator-only non-read permissions
170
170
  Managed Composio toolkit auth configs are available in AgentKit Cloud when configured
171
171
  Provider model is supported by AgentKit
172
172
  schema.sql is idempotent
@@ -89,6 +89,7 @@ defineTool({
89
89
 
90
90
  ## Safety Rules
91
91
 
92
+ - An Agent Capsule is executable TypeScript. Run AgentKit commands only in Capsules whose config, tools, evals, and sync code you trust; AgentKit does not sandbox Capsule code from the local filesystem, network, or process environment.
92
93
  - `.env` is local-only.
93
94
  - `.env.schema` is the committed contract for local secret names.
94
95
  - AgentKit local commands load `.env` directly so inspect, chat, tools, and evals share the same secret loader.
@@ -98,6 +99,8 @@ defineTool({
98
99
  - A tool receives only secrets listed in that tool.
99
100
  - Avoid direct `process.env` reads inside tools.
100
101
  - Use `permissions` to describe external capabilities.
102
+ - Permissions ending in `:read` may run from chat, channels, and evals. Any other declared permission is operator-only and must be invoked directly with `agentkit tool <name> --input '<json>'` after reviewing the exact action.
103
+ - Local dev access accepts only loopback Host/Origin values and limits JSON and webhook bodies to 1 MiB. Keep public tunnels behind authenticated access instead of weakening these checks.
101
104
  - Add timeouts to network tools.
102
105
  - Treat hosted deploy URLs as addresses, not access control.
103
106
  - Use deploy access tokens for hosted chat, hosted conversation reads, hosted trace reads, and any client app that talks to AgentKit Cloud.
@@ -0,0 +1,67 @@
1
+ # Use Jev In A Capsule Tool
2
+
3
+ Use this when the owner asks their coding agent (Codex, Claude Code, or another agent) to build a capsule capability with TypeSafe/Jev, such as qualifying leads, ranking candidates, selecting a handler, or checking evidence.
4
+
5
+ Implement the requested behavior through the existing `defineTool` contract. Jev supplies typed judgments inside the tool; the capsule's conversational provider continues through AgentKit. Keep questions and business criteria in the tool code, shaped by the owner's brief. No special AgentKit provider, runtime hook, or globally enabled Jev tool is needed.
6
+
7
+ ## Read The Relevant TypeSafe Guidance
8
+
9
+ Read the live [TypeSafe docs index](https://docs.typesafe.ai/llms.txt), [building guide](https://docs.typesafe.ai/concepts/how-to-build-with-system-one), and the relevant primitive before designing the judgment:
10
+
11
+ - [Choice](https://docs.typesafe.ai/primitives/choice): select from defined alternatives; include “none” or “insufficient evidence” when appropriate.
12
+ - [Noul](https://docs.typesafe.ai/primitives/noul): estimate the probability of a yes/no condition. It has no separate confidence field.
13
+ - [Score](https://docs.typesafe.ai/primitives/score): rate along concrete ordered levels.
14
+
15
+ Use the closest cookbook from the index for the requested workflow. If the official `typesafe-ai` skill is installed, use it; it is optional and this workflow does not depend on a personal skill or helper being present. Check the current [HTTP contract](https://docs.typesafe.ai/api) when using the example, or the [JavaScript SDK](https://docs.typesafe.ai/sdk/javascript) if the capsule already uses it. Verify SDK compatibility with the capsule's deploy target before adding a dependency.
16
+
17
+ ## Build The Requested Capability
18
+
19
+ 1. Inspect the capsule's tools, config, prompts, and evals. Reuse an existing domain tool when Jev belongs inside its workflow.
20
+ 2. Adapt `skills/agentkit-tools/examples/jev-service-fit.tool.md` into `tools/<name>.ts`. The example uses native `fetch`, so no TypeSafe package is required. Register the export in the existing `agentkit.config.ts` tools array without replacing other config.
21
+ 3. Define narrow questions against relevant state: the client's request, available candidates, service definitions, or supporting evidence. Question IDs are only lookup keys; include the question's meaning in its instructions. Batch independent questions over the same state; sequence calls only when a later question needs an earlier result.
22
+ 4. Keep exact calculations, lookups, permission checks, and execution in code. Jev's output is evidence for a decision, never authorization for an external action. Preserve any existing tool permission requirements.
23
+ 5. Update `prompts/instructions.md` with when to call the tool and how to handle uncertain results or service failures. For the example, assess service fit before recommending the website service; ask for clarification when evidence is ambiguous, and do not treat a fit score as a quote, booking, or approval.
24
+ 6. Add deterministic checks and a persisted tool-call eval. Test the owner's actual criteria separately with labeled examples before choosing operational thresholds. [Confidence](https://docs.typesafe.ai/confidence) measures distribution concentration, not guaranteed correctness; a Noul near 0.5 represents uncertainty about yes/no, not medium intensity.
25
+
26
+ ## Secrets And External Data
27
+
28
+ Declare `TYPESAFE_API_KEY` in the tool's `secrets` array and add the name with an empty value to `.env.schema`:
29
+
30
+ ```dotenv
31
+ TYPESAFE_API_KEY=
32
+ ```
33
+
34
+ Set the real value through the local secret prompt:
35
+
36
+ ```sh
37
+ npm run agentkit -- env set TYPESAFE_API_KEY
38
+ ```
39
+
40
+ Read it only from `ctx.secrets.TYPESAFE_API_KEY` inside the tool. For a hosted capsule, follow [Prepare Deploy](prepare-deploy.md) and upload the key through managed secrets:
41
+
42
+ ```sh
43
+ npm run agentkit -- secret set TYPESAFE_API_KEY --from-local-env
44
+ ```
45
+
46
+ Send only the state needed for the judgment. Tool inputs and outputs are recorded, so avoid secrets, unnecessary client identifiers, and full conversation histories. Do not echo upstream response bodies or headers in errors. Forward `ctx.signal`, set a tool timeout, and validate returned values before using them. A timeout, 429, invalid response, or missing key must remain an explicit failure or a deliberately designed fallback; never turn it into a successful judgment.
47
+
48
+ ## Verify
49
+
50
+ The bundled example includes a fixture eval. In an isolated offline test capsule, supply a non-secret dummy `TYPESAFE_API_KEY`: AgentKit resolves declared secrets before entering the tool, even for eval fixtures. The fixture branch runs only in `eval` or `test`; `test/fake` as the conversational provider alone does not prevent live tool calls. Never upload a dummy key to a hosted capsule or substitute fixtures for production failures.
51
+
52
+ ```sh
53
+ npm run typecheck
54
+ npm run eval
55
+ npm run agentkit -- inspect
56
+ ```
57
+
58
+ For a live check with the real key, use synthetic data:
59
+
60
+ ```sh
61
+ npm run agentkit -- tool assess_service_fit --input '{"message":"I need a website for my bakery."}'
62
+ npm run agentkit -- conversations list
63
+ ```
64
+
65
+ Expect a probability between 0 and 1 and `evalFixture: false`; inspect the recorded call without exposing the key. The fixture verifies wiring, not Jev's accuracy. Also test invalid inputs, unavailable service, malformed responses, and cancellation with mocked HTTP responses. Measure actual quality, latency, and cost before expanding usage.
66
+
67
+ New capsules receive the example automatically. Existing capsules can update AgentKit and run `npm run agentkit -- skills sync` to refresh bundled skills; preserve any local skill edits before syncing.
@@ -33,7 +33,8 @@ The capsule root is the runtime boundary. Run AgentKit commands from the directo
33
33
  Current commands:
34
34
 
35
35
  ```sh
36
- agentkit new <name> [--template blank|support|dentista] [--no-install]
36
+ agentkit new [name] [--template blank|support|dentista] [--no-install]
37
+ agentkit new .
37
38
  agentkit dev [--port <number>]
38
39
  agentkit open
39
40
  agentkit chat-ui --deploy
@@ -119,7 +120,7 @@ Use `agentkit feedback create` when AgentKit itself fails, confuses the coding a
119
120
 
120
121
  On Windows PowerShell, if `npm.ps1` or `npx.ps1` is blocked with `PSSecurityException`, run capsule scripts through the `.cmd` shims instead of changing the workflow. Examples: `npx.cmd @andreprado/agentkit@alpha new demo --template blank`, `npm.cmd run agentkit -- inspect`, `npm.cmd run agentkit -- knowledge sync`, and `npm.cmd run eval`.
121
122
 
122
- Managed Composio is configured with `composioManaged({...})` in `agentkit.config.ts` and is paid hosted AgentKit infrastructure. It requires a non-anonymous AgentKit Cloud deploy with `managed_composio`, uses one Composio settings profile per agent, injects `COMPOSIO_API_KEY` as an AgentKit-managed secret, resolves toolkit auth configs from AgentKit Cloud, validates toolkit readiness during `agentkit deploy doctor`, and exposes the generated `agentkit_composio_execute` tool only for explicit configured action slugs. Calendar starters should include `GOOGLECALENDAR_EVENTS_LIST`, `GOOGLECALENDAR_CREATE_EVENT`, and `GOOGLECALENDAR_UPDATE_EVENT`; create-event calls must pass UTC `start_datetime` plus explicit duration. Managed external write actions require tool input `confirmed: true` by default unless the integration sets `confirmExternalWrites: false`. See `docs/guides/add-managed-composio.md`.
123
+ Managed Composio is configured with `composioManaged({...})` in `agentkit.config.ts` and is paid hosted AgentKit infrastructure. It requires a non-anonymous AgentKit Cloud deploy with `managed_composio`, uses one Composio settings profile per agent, injects `COMPOSIO_API_KEY` as an AgentKit-managed secret, resolves toolkit auth configs from AgentKit Cloud, validates toolkit readiness during `agentkit deploy doctor`, and exposes the generated `agentkit_composio_execute` tool only for explicit configured action slugs. Calendar starters should include `GOOGLECALENDAR_EVENTS_LIST`, `GOOGLECALENDAR_CREATE_EVENT`, and `GOOGLECALENDAR_UPDATE_EVENT`; create-event calls must pass UTC `start_datetime` plus explicit duration. An integration containing external write actions is operator-only; invoke it directly with `agentkit tool`, and pass `confirmed: true` for writes unless the integration disables that secondary check. See `docs/guides/add-managed-composio.md`.
123
124
 
124
125
  ## Create And Test A Capsule
125
126
 
@@ -139,6 +140,8 @@ npm run agentkit -- conversations list
139
140
  npm run agentkit -- inspect
140
141
  ```
141
142
 
143
+ Run `agentkit new` without a name in an interactive terminal to be prompted for the project folder. Use `agentkit new .` to create the capsule in the current directory. Non-interactive scripts should pass a name or `.` explicitly.
144
+
142
145
  Expected first chat output:
143
146
 
144
147
  ```txt
@@ -402,6 +405,7 @@ Rules:
402
405
  - `runtime: "edge"` is required when `channels` are configured.
403
406
  - Channel names are stable lowercase identifiers and must be unique.
404
407
  - Config stores secret names only, never secret values.
408
+ - UAZAPI and Zapster WhatsApp channels require `UAZAPI_WEBHOOK_TOKEN` and `ZAPSTER_WEBHOOK_TOKEN`; webhooks without the matching query token are rejected.
405
409
  - AgentKit owns channel webhook URLs, dedupe, identities, queue state, and delivery logs.
406
410
  - Do not store channel plumbing in the user's Turso database.
407
411
  - Use `buffer.mode: "debounce"` when a channel should coalesce rapid client messages into one agent run.
@@ -450,6 +454,7 @@ Zapster WhatsApp required secrets:
450
454
  ZAPSTER_API_KEY
451
455
  ZAPSTER_INSTANCE_ID
452
456
  ZAPSTER_WEBHOOK_ID
457
+ ZAPSTER_WEBHOOK_TOKEN
453
458
  ```
454
459
 
455
460
  UAZAPI WhatsApp required secrets:
@@ -457,8 +462,11 @@ UAZAPI WhatsApp required secrets:
457
462
  ```txt
458
463
  UAZAPI_BASE_URL
459
464
  UAZAPI_TOKEN
465
+ UAZAPI_WEBHOOK_TOKEN
460
466
  ```
461
467
 
468
+ `UAZAPI_WEBHOOK_TOKEN` and `ZAPSTER_WEBHOOK_TOKEN` are AgentKit-owned secrets generated by the user, not provider-issued credentials. For local `agentkit dev`, expose the printed port through an HTTPS tunnel and register the exact `/channels/<name>/whatsapp/<provider>/webhook?token=<secret>` URL. Only authenticated channel webhook routes accept a tunnel host; other local endpoints remain loopback-only.
469
+
462
470
  Evolution API WhatsApp required secrets:
463
471
 
464
472
  ```txt
@@ -569,7 +577,7 @@ agentkit channels deliveries list support-telegram
569
577
  agentkit channels deliveries show <delivery-id>
570
578
  ```
571
579
 
572
- `channels connect` creates or refreshes the channel resource, validates secrets, runs provider setup when supported, then runs the official synthetic smoke. `channels setup` is read-only by default. `channels setup <telegram-name> --apply` calls Telegram `setWebhook` and requires `TELEGRAM_BOT_TOKEN` plus `TELEGRAM_WEBHOOK_SECRET`. `channels setup <uazapi-whatsapp-name> --apply` calls UAZAPI `/webhook` and requires `UAZAPI_BASE_URL` plus `UAZAPI_TOKEN`. `channels setup <evolution-whatsapp-name> --apply` calls Evolution API `/webhook/set/{instance}` and requires `EVOLUTION_API_BASE_URL`, `EVOLUTION_API_KEY`, `EVOLUTION_INSTANCE_NAME`, and `EVOLUTION_WEBHOOK_TOKEN`.
580
+ `channels connect` creates or refreshes the channel resource, validates secrets, runs provider setup when supported, then runs the official synthetic smoke. `channels setup` is read-only by default. `channels setup <telegram-name> --apply` calls Telegram `setWebhook` and requires `TELEGRAM_BOT_TOKEN` plus `TELEGRAM_WEBHOOK_SECRET`. `channels setup <uazapi-whatsapp-name> --apply` calls UAZAPI `/webhook` and requires `UAZAPI_BASE_URL`, `UAZAPI_TOKEN`, and `UAZAPI_WEBHOOK_TOKEN`. `channels setup <evolution-whatsapp-name> --apply` calls Evolution API `/webhook/set/{instance}` and requires `EVOLUTION_API_BASE_URL`, `EVOLUTION_API_KEY`, `EVOLUTION_INSTANCE_NAME`, and `EVOLUTION_WEBHOOK_TOKEN`.
573
581
 
574
582
  Discord slash-command mode validates `X-Signature-Ed25519` and `X-Signature-Timestamp` against `DISCORD_PUBLIC_KEY`, answers signed `PING` requests with `type: 1`, acknowledges slash commands with a deferred response, then sends the final answer as an interaction follow-up. Discord bot mode uses `DISCORD_BOT_TOKEN`, Discord Gateway `MESSAGE_CREATE`, Message Content Intent, and `/channels/<channel_id>/messages` bot replies. Discord channels support buffering but do not support `audio` in V1.
575
583
 
@@ -583,8 +591,8 @@ AGENTKIT_RUN_EVOLUTION_CHANNEL_TESTS=1 bun test
583
591
  ```
584
592
 
585
593
  Telegram smoke also requires `TELEGRAM_BOT_TOKEN`, `TELEGRAM_WEBHOOK_SECRET`, and `AGENTKIT_TELEGRAM_WEBHOOK_URL`.
586
- Zapster smoke also requires `ZAPSTER_API_KEY`, `AGENTKIT_ZAPSTER_SEND_URL`, and `AGENTKIT_ZAPSTER_TO`.
587
- UAZAPI smoke also requires `UAZAPI_BASE_URL`, `UAZAPI_TOKEN`, and `AGENTKIT_UAZAPI_TO`.
594
+ Zapster smoke also requires `ZAPSTER_API_KEY`, `ZAPSTER_WEBHOOK_TOKEN`, `AGENTKIT_ZAPSTER_SEND_URL`, and `AGENTKIT_ZAPSTER_TO`.
595
+ UAZAPI smoke also requires `UAZAPI_BASE_URL`, `UAZAPI_TOKEN`, `UAZAPI_WEBHOOK_TOKEN`, and `AGENTKIT_UAZAPI_TO`.
588
596
  Evolution smoke also requires `EVOLUTION_API_BASE_URL`, `EVOLUTION_API_KEY`, `EVOLUTION_INSTANCE_NAME`, and `AGENTKIT_EVOLUTION_TO`.
589
597
 
590
598
  ## Tool Contract
@@ -646,6 +654,7 @@ Tool runtime rules:
646
654
  - `timeoutMs` overrides the default;
647
655
  - tool calls are saved in AgentKit-managed local storage;
648
656
  - secret values are redacted before storage.
657
+ - permissions ending in `:read` may run automatically; any other declared permission requires a reviewed direct `agentkit tool` invocation and is blocked from chat, channels, and evals;
649
658
  - tools that need SQL use canonical `ctx.db`; `ctx.database` and `ctx.storage.sql` are supported aliases;
650
659
  - tools can use `ctx.db.batch([...])` for atomic writes; local tools can also use `ctx.db.transaction(async (tx) => ...)`;
651
660
  - tools can inspect `ctx.runtime` with `{ environment, invocation, target, database }`;
@@ -849,6 +858,8 @@ POST /v1/chat
849
858
  GET /v1/conversations
850
859
  GET /v1/conversations/:id
851
860
  GET /v1/conversations/:id/trace
861
+ POST /channels/<name>/<type>/<provider>/webhook
862
+ POST /channels/<name>/webhook
852
863
  ```
853
864
 
854
865
  Chat request:
@@ -1000,6 +1011,7 @@ docs/
1000
1011
  Local `.env` is development only. Use `.env.schema` as the committed secret-name contract; local AgentKit commands load `.env` directly. Hosted deploys require an AgentKit Cloud account with `cloudflare_deploy_alpha` or purchased/manual deploy slots. First-time paid access uses `agentkit billing checkout --slots <count>` and `agentkit billing claim billint_... --secret bsec_...`; existing accounts use `agentkit login --token ...`. Hosted secrets use `agentkit secret set/list/unset` or `agentkit secret sync --from-local`. Prefer `--stdin`, `--from-env`, `--from-local-env`, or sync from local `.env` so secret values do not appear in shell history. Inline `<VALUE>` forms exist only for compatibility and simple non-sensitive values.
1001
1012
 
1002
1013
  Tools are a security boundary. A tool must declare every secret it needs. The runtime injects only tool-declared secrets.
1014
+ Agent Capsules are trusted executable TypeScript, not sandboxed configuration. Run AgentKit commands only in Capsules whose config, tools, evals, and sync modules you trust.
1003
1015
 
1004
1016
  ## Hosted Deploy Contract
1005
1017
 
package/docs/llms.txt CHANGED
@@ -8,6 +8,7 @@ Task guides:
8
8
 
9
9
  - Create a capsule: `docs/guides/create-agent.md`
10
10
  - Add a TypeScript tool: `docs/guides/add-tool.md`
11
+ - Use TypeSafe/Jev inside a capsule tool: `docs/guides/use-jev.md`
11
12
  - Add Knowledge from local docs/CSVs: `docs/guides/add-knowledge.md`
12
13
  - Run or prepare evals: `docs/guides/run-evals.md`
13
14
  - Improve from production traces: `docs/guides/improve-from-production.md`
@@ -35,8 +36,9 @@ Task guides:
35
36
  Current local commands:
36
37
 
37
38
  ```sh
38
- agentkit new <name> --template blank|support|dentista
39
- agentkit new <name> --template blank --no-install
39
+ agentkit new [name] --template blank|support|dentista
40
+ agentkit new . --template blank
41
+ agentkit new [name] --template blank --no-install
40
42
  agentkit docs full
41
43
  agentkit env set <NAME> --stdin
42
44
  agentkit env list
@@ -119,6 +121,10 @@ POST /v1/chat
119
121
  GET /v1/conversations
120
122
  GET /v1/conversations/:id
121
123
  GET /v1/conversations/:id/trace
124
+ POST /channels/<name>/<type>/<provider>/webhook
125
+ POST /channels/<name>/webhook
122
126
  ```
123
127
 
128
+ Only authenticated channel webhook routes may arrive through a public HTTPS tunnel. Other local endpoints remain loopback-only. UAZAPI and Zapster use user-generated AgentKit URL secrets in `?token=...`; the providers do not issue those values.
129
+
124
130
  Local `.env` is for development only. Use `.env.schema` as the committed secret-name contract; local AgentKit commands load `.env` directly. Hosted deploys require an AgentKit Cloud account with `cloudflare_deploy_alpha` or purchased/manual deploy slots. Use `agentkit billing checkout` + `agentkit billing claim` for first-time paid access, or `agentkit login --token ...` when the user already has an `agk_user_...` token. Production uses managed secrets in the hosted contract.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andreprado/agentkit",
3
- "version": "0.1.0-alpha.24",
3
+ "version": "0.1.0-alpha.26",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "repository": {
@@ -31,10 +31,9 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@earendil-works/pi-ai": "^0.75.5",
34
- "@earendil-works/pi-coding-agent": "^0.75.5",
35
34
  "@libsql/client": "^0.15.15",
36
- "esbuild": "^0.28.0",
37
- "tsx": "^4.22.3",
35
+ "esbuild": "^0.28.2",
36
+ "tsx": "^4.23.12",
38
37
  "typebox": "^1.1.38"
39
38
  },
40
39
  "devDependencies": {
@@ -1221,7 +1221,7 @@ function defaultChannelSecretsForCli(type: string, provider: string, mode?: "int
1221
1221
  }
1222
1222
 
1223
1223
  if (type === "whatsapp" && provider === "zapster") {
1224
- return ["ZAPSTER_API_KEY", "ZAPSTER_INSTANCE_ID", "ZAPSTER_WEBHOOK_ID"];
1224
+ return ["ZAPSTER_API_KEY", "ZAPSTER_INSTANCE_ID", "ZAPSTER_WEBHOOK_ID", "ZAPSTER_WEBHOOK_TOKEN"];
1225
1225
  }
1226
1226
 
1227
1227
  if (type === "whatsapp" && provider === "meta") {
@@ -1229,7 +1229,7 @@ function defaultChannelSecretsForCli(type: string, provider: string, mode?: "int
1229
1229
  }
1230
1230
 
1231
1231
  if (type === "whatsapp" && provider === "uazapi") {
1232
- return ["UAZAPI_BASE_URL", "UAZAPI_TOKEN"];
1232
+ return ["UAZAPI_BASE_URL", "UAZAPI_TOKEN", "UAZAPI_WEBHOOK_TOKEN"];
1233
1233
  }
1234
1234
 
1235
1235
  if (type === "whatsapp" && provider === "evolution") {
package/src/cli/help.ts CHANGED
@@ -13,7 +13,7 @@ Usage:
13
13
  agentkit <command> [options]
14
14
 
15
15
  Start:
16
- agentkit new <name> [--template blank|support|dentista] [--no-install]
16
+ agentkit new [name] [--template blank|support|dentista] [--no-install]
17
17
  agentkit dev
18
18
  agentkit open
19
19
  agentkit chat-ui --deploy
@@ -59,7 +59,7 @@ export function renderCommandReference(): string {
59
59
  return `AgentKit Command Reference
60
60
 
61
61
  Usage:
62
- agentkit new <name> [--template blank|support|dentista] [--no-install]
62
+ agentkit new [name] [--template blank|support|dentista] [--no-install]
63
63
  agentkit dev [--port <number>]
64
64
  agentkit open
65
65
  agentkit chat-ui --deploy [--port <number>] [--token-file <path>]
@@ -189,13 +189,15 @@ Examples:
189
189
  agentkit tool lookup_order --input '{"orderId":"A100"}'
190
190
  agentkit eval run
191
191
 
192
+ agentkit new
193
+ agentkit new .
192
194
  agentkit new clara-dentista --template dentista
193
195
  `;
194
196
  }
195
197
 
196
198
  export function renderCommandHelp(command: string): string {
197
199
  const usage: Record<string, string> = {
198
- new: "agentkit new <name> [--template blank|support|dentista] [--no-install]",
200
+ new: "agentkit new [name] [--template blank|support|dentista] [--no-install]",
199
201
  dev: "agentkit dev [--port <number>]",
200
202
  open: "agentkit open",
201
203
  "chat-ui": "agentkit chat-ui --deploy [--port <number>] [--token-file <path>]",
package/src/cli/index.ts CHANGED
@@ -31,6 +31,7 @@ import { inspectAgentCapsule } from "../runtime/inspect";
31
31
  import { AgentKitError, isAgentKitError } from "../runtime/errors";
32
32
  import { prepareVpsDeploy } from "../runtime/targets/vps/deploy";
33
33
  import { parseArgs, isHelpRequested, type ParsedArgs } from "./args";
34
+ import { resolveNewProjectName } from "./new-command";
34
35
  import {
35
36
  defaultAgentKitDevPort,
36
37
  defaultDeployChatAccessTokenName,
@@ -114,14 +115,10 @@ async function main() {
114
115
  warnIfUnsupportedNode();
115
116
 
116
117
  if (args.command === "new") {
117
- const [name] = args.positional;
118
+ const name = await resolveNewProjectName(args.positional);
118
119
  const template = String(args.flags.template ?? "blank");
119
120
  const shouldInstall = args.flags["no-install"] !== true;
120
121
 
121
- if (!name) {
122
- throw new Error("Missing project name. Usage: agentkit new <name> [--template blank|support|dentista] [--no-install]");
123
- }
124
-
125
122
  const result = await createProject({ name, template, cwd: process.cwd() });
126
123
  console.log(`Created ${result.name} at ${result.path}`);
127
124