@andreprado/agentkit 0.1.0-alpha.20 → 0.1.0-alpha.22
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/README.md +1 -0
- package/docs/guides/add-channel.md +75 -4
- package/docs/guides/add-managed-composio.md +3 -1
- package/docs/guides/add-tool.md +6 -3
- package/docs/guides/channel-security.md +32 -1
- package/docs/guides/connect-whatsapp-evolution.md +121 -0
- package/docs/guides/connect-whatsapp-uazapi.md +126 -0
- package/docs/guides/create-agent.md +6 -4
- package/docs/guides/debug-channel.md +3 -3
- 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 +82 -9
- package/docs/llms.txt +9 -2
- package/package.json +1 -1
- package/src/cli/commands/channels.ts +285 -14
- package/src/cli/deploy-chat-ui.ts +86 -15
- package/src/cli/help.ts +2 -2
- package/src/cli/index.ts +107 -8
- package/src/index.ts +42 -5
- package/src/providers/pi.ts +12 -2
- package/src/runtime/channel-test-harness.ts +14 -1
- package/src/runtime/channels/generic-webhook.ts +225 -0
- package/src/runtime/channels/whatsapp-evolution.ts +1357 -0
- package/src/runtime/channels/whatsapp-uazapi.ts +1327 -0
- package/src/runtime/channels.ts +1 -1
- package/src/runtime/chat.ts +7 -1
- package/src/runtime/config.ts +40 -5
- package/src/runtime/core/targets.ts +5 -5
- package/src/runtime/dev-server.ts +21 -5
- package/src/runtime/evals.ts +39 -24
- package/src/runtime/targets/cloudflare/build.ts +23 -3
- 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 +22 -1
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +1 -1
- package/src/templates/skills/agentkit-channels/SKILL.md +25 -2
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +1 -1
- package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +57 -0
- package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +61 -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
package/README.md
CHANGED
|
@@ -67,6 +67,7 @@ agentkit secret set OPENAI_API_KEY --from-local-env
|
|
|
67
67
|
agentkit deploy
|
|
68
68
|
agentkit deploy status
|
|
69
69
|
agentkit channels test support-telegram --message "hello"
|
|
70
|
+
agentkit channels connect webhook n8n-webhook
|
|
70
71
|
agentkit transcribe smoke --provider groq
|
|
71
72
|
agentkit chat-ui --deploy
|
|
72
73
|
```
|
|
@@ -6,7 +6,7 @@ Add a hosted messaging channel to an Agent Capsule, create the hosted channel re
|
|
|
6
6
|
|
|
7
7
|
## When To Use It
|
|
8
8
|
|
|
9
|
-
Use this when the agent should receive messages from website chat, Telegram, WhatsApp, or
|
|
9
|
+
Use this when the agent should receive messages from website chat, Telegram, WhatsApp, Discord, Slack, or a generic webhook through AgentKit-owned channel infrastructure.
|
|
10
10
|
|
|
11
11
|
## Commands
|
|
12
12
|
|
|
@@ -19,7 +19,10 @@ agentkit channels add telegram support-telegram
|
|
|
19
19
|
agentkit channels connect discord support-discord
|
|
20
20
|
agentkit channels connect discord server-discord --mode bot
|
|
21
21
|
agentkit channels connect slack support-slack
|
|
22
|
+
agentkit channels connect webhook n8n-webhook
|
|
22
23
|
agentkit channels add whatsapp support-whatsapp --provider zapster
|
|
24
|
+
agentkit channels connect whatsapp support-uazapi --provider uazapi
|
|
25
|
+
agentkit channels connect whatsapp main-whatsapp --provider evolution
|
|
23
26
|
agentkit channels setup support-telegram
|
|
24
27
|
agentkit channels status support-telegram
|
|
25
28
|
agentkit channels test support-telegram --message "hello"
|
|
@@ -31,15 +34,16 @@ Use `--api <url>` only when the owner gives you a non-default AgentKit Cloud API
|
|
|
31
34
|
|
|
32
35
|
## Files Created Or Edited
|
|
33
36
|
|
|
34
|
-
- `agentkit.config.ts`: declare channel config with `websiteChannel`, `telegramChannel`, `whatsappChannel`, `discordChannel`, or `
|
|
37
|
+
- `agentkit.config.ts`: declare channel config with `websiteChannel`, `telegramChannel`, `whatsappChannel`, `discordChannel`, `slackChannel`, or `webhookChannel`.
|
|
35
38
|
- `.agentkit/deploy.json`: written by `agentkit deploy`; used by `agentkit channels ...`.
|
|
36
39
|
- No user Turso tables: AgentKit owns channel resources, dedupe, identities, queue state, and delivery logs.
|
|
37
40
|
- Website channel clients must send `AGENTKIT_WEBSITE_CHANNEL_TOKEN` as `Authorization: Bearer <token>` or `X-AgentKit-Channel-Token`.
|
|
41
|
+
- Generic webhook clients must send `AGENTKIT_WEBHOOK_SECRET` as `Authorization: Bearer <token>`, `X-AgentKit-Webhook-Secret`, or `X-AgentKit-Webhook-Signature: sha256=<hmac>`.
|
|
38
42
|
|
|
39
43
|
## Minimal Working Example
|
|
40
44
|
|
|
41
45
|
```ts
|
|
42
|
-
import { defineAgent, discordChannel, slackChannel, telegramChannel, whatsappChannel, websiteChannel } from "@andreprado/agentkit";
|
|
46
|
+
import { defineAgent, discordChannel, slackChannel, telegramChannel, webhookChannel, whatsappChannel, websiteChannel } from "@andreprado/agentkit";
|
|
43
47
|
|
|
44
48
|
export default defineAgent({
|
|
45
49
|
name: "support-agent",
|
|
@@ -52,9 +56,12 @@ export default defineAgent({
|
|
|
52
56
|
websiteChannel({ name: "website-chat" }),
|
|
53
57
|
telegramChannel({ name: "support-telegram" }),
|
|
54
58
|
whatsappChannel({ name: "support-whatsapp", provider: "zapster" }),
|
|
59
|
+
whatsappChannel({ name: "support-uazapi", provider: "uazapi" }),
|
|
60
|
+
whatsappChannel({ name: "main-whatsapp", provider: "evolution" }),
|
|
55
61
|
discordChannel({ name: "support-discord" }),
|
|
56
62
|
discordChannel({ name: "server-discord", mode: "bot" }),
|
|
57
63
|
slackChannel({ name: "support-slack" }),
|
|
64
|
+
webhookChannel({ name: "n8n-webhook" }),
|
|
58
65
|
],
|
|
59
66
|
access: { mode: "public" },
|
|
60
67
|
storage: { driver: "agentkit" },
|
|
@@ -95,6 +102,57 @@ agentkit channels buffers retry support-whatsapp <conversation-id>
|
|
|
95
102
|
|
|
96
103
|
Discord supports buffering for slash-command interactions and bot-mode server messages, but it does not support `audio` in V1.
|
|
97
104
|
|
|
105
|
+
## Generic Webhooks
|
|
106
|
+
|
|
107
|
+
Use `webhookChannel` when n8n, Make, Zapier, Pipedream, or a custom server should push a text event into the agent.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
webhookChannel({
|
|
111
|
+
name: "n8n-webhook",
|
|
112
|
+
})
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
After deploy:
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
agentkit channels connect webhook n8n-webhook
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The hosted webhook URL is:
|
|
122
|
+
|
|
123
|
+
```txt
|
|
124
|
+
https://<deploy-host>/channels/n8n-webhook/webhook
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Send canonical JSON:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"event_id": "evt_123",
|
|
132
|
+
"external_id": "customer_123",
|
|
133
|
+
"message": "hello from n8n"
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`event_id` is required for replay protection. `external_id` is optional but recommended; AgentKit hashes it before storing the channel identity and uses it to continue the same conversation. If `external_id` is omitted, the event id becomes the conversation identity and each event is treated as its own conversation.
|
|
138
|
+
|
|
139
|
+
Authenticate with a shared secret:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
curl -X POST https://<deploy-host>/channels/n8n-webhook/webhook \
|
|
143
|
+
-H 'content-type: application/json' \
|
|
144
|
+
-H 'authorization: Bearer <AGENTKIT_WEBHOOK_SECRET>' \
|
|
145
|
+
-d '{"event_id":"evt_123","external_id":"customer_123","message":"hello from n8n"}'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
For HMAC auth, compute `HMAC-SHA256(raw JSON body, AGENTKIT_WEBHOOK_SECRET)` and send:
|
|
149
|
+
|
|
150
|
+
```txt
|
|
151
|
+
X-AgentKit-Webhook-Signature: sha256=<hex digest>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Generic webhooks are inbound-only in V1. The agent run is queued and delivery logs show the result; AgentKit does not call back into n8n unless the agent has a separate tool that does so.
|
|
155
|
+
|
|
98
156
|
## Auto Transcribe Audio
|
|
99
157
|
|
|
100
158
|
Use `transcription` at the agent level and `audio.mode: "transcribe"` on each Telegram or WhatsApp channel that should accept voice notes or audio files.
|
|
@@ -125,6 +183,16 @@ export default defineAgent({
|
|
|
125
183
|
provider: "zapster",
|
|
126
184
|
audio: { mode: "transcribe" },
|
|
127
185
|
}),
|
|
186
|
+
whatsappChannel({
|
|
187
|
+
name: "support-uazapi",
|
|
188
|
+
provider: "uazapi",
|
|
189
|
+
audio: { mode: "transcribe" },
|
|
190
|
+
}),
|
|
191
|
+
whatsappChannel({
|
|
192
|
+
name: "main-whatsapp",
|
|
193
|
+
provider: "evolution",
|
|
194
|
+
audio: { mode: "transcribe" },
|
|
195
|
+
}),
|
|
128
196
|
],
|
|
129
197
|
access: { mode: "public" },
|
|
130
198
|
storage: { driver: "agentkit" },
|
|
@@ -149,6 +217,8 @@ Processing order:
|
|
|
149
217
|
5. The transcription adapter sends the file to the configured transcription provider.
|
|
150
218
|
6. The agent receives a text message containing the transcript.
|
|
151
219
|
|
|
220
|
+
Zapster audio downloads from trusted HTTPS Zapster media URLs. UAZAPI audio downloads through UAZAPI `/message/download` with base64 return enabled. Evolution audio downloads through Evolution API `/chat/getBase64FromMediaMessage/{instance}` with base64 return enabled. AgentKit does not fetch arbitrary UAZAPI or Evolution webhook media hosts.
|
|
221
|
+
|
|
152
222
|
V1 keeps the raw audio in memory for the request path and delivery metadata only records redacted status/error fields. `rawAudioTtlSeconds` is part of the manifest contract for future object-storage retention, but V1 does not persist raw audio by default.
|
|
153
223
|
|
|
154
224
|
## Safety Rules
|
|
@@ -167,6 +237,7 @@ npm run typecheck
|
|
|
167
237
|
bun test
|
|
168
238
|
agentkit inspect
|
|
169
239
|
agentkit channels list
|
|
240
|
+
agentkit channels test n8n-webhook --message "hello"
|
|
170
241
|
agentkit channels test support-telegram --message "hello"
|
|
171
242
|
agentkit channels test-audio support-telegram --fixture voice-note
|
|
172
243
|
agentkit transcribe smoke --provider groq
|
|
@@ -175,7 +246,7 @@ agentkit channels buffers list support-telegram
|
|
|
175
246
|
```
|
|
176
247
|
|
|
177
248
|
Expected hosted status includes `NAME`, `TYPE`, `PROVIDER`, `STATUS`, and `LAST_EVENT`. Secret output is name plus `set` or `missing`, never the value.
|
|
178
|
-
Outbound provider success is `provider_sent`.
|
|
249
|
+
Outbound provider success is `provider_sent`. `adapter_stubbed` means no outbound provider call was made, either because explicit dry-run mode is enabled or the channel is inbound-only.
|
|
179
250
|
|
|
180
251
|
## Troubleshooting
|
|
181
252
|
|
|
@@ -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
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Goal
|
|
4
4
|
|
|
5
|
-
Configure website, Telegram, WhatsApp, Discord, and
|
|
5
|
+
Configure website, Telegram, WhatsApp, Discord, Slack, and generic webhook channels without leaking secrets, storing raw provider payloads, or treating public webhook URLs as authorization.
|
|
6
6
|
|
|
7
7
|
## When To Use It
|
|
8
8
|
|
|
@@ -33,6 +33,9 @@ agentkit channels deliveries show <delivery-id>
|
|
|
33
33
|
- Do not store raw webhook bodies, raw audio, or provider secret values in tools, prompts, evals, fixtures, or delivery notes.
|
|
34
34
|
- Do not expose Discord interaction tokens or bot tokens. Interaction tokens are reply tokens, not public identifiers.
|
|
35
35
|
- Do not expose Slack bot tokens or signing secrets. Slack signing secrets authenticate webhook origin; Slack bot tokens authorize outbound replies.
|
|
36
|
+
- Do not expose `AGENTKIT_WEBHOOK_SECRET`. Generic webhook clients must authenticate with bearer/header token auth or an HMAC signature over the exact raw body.
|
|
37
|
+
- 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.
|
|
38
|
+
- 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.
|
|
36
39
|
- Inspect delivery IDs, hashes, redacted metadata, and statuses instead of raw provider payloads.
|
|
37
40
|
- Keep channel plumbing out of the agent's application database. The user's Turso tables are for the agent's business data.
|
|
38
41
|
- Enable audio transcription only when the capsule declares a transcription provider and bounded `limits`.
|
|
@@ -112,6 +115,34 @@ slackChannel({
|
|
|
112
115
|
|
|
113
116
|
AgentKit validates `X-Slack-Signature` and `X-Slack-Request-Timestamp` against the raw body, rejects stale timestamps, answers Slack `url_verification` with the literal challenge, skips bot/subtype messages, and sends replies with Slack control mentions escaped.
|
|
114
117
|
|
|
118
|
+
Generic webhooks use an AgentKit shared secret:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
webhookChannel({
|
|
122
|
+
name: "n8n-webhook",
|
|
123
|
+
secrets: ["AGENTKIT_WEBHOOK_SECRET"],
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
AgentKit validates `Authorization: Bearer <secret>`, `X-AgentKit-Webhook-Secret`, or `X-AgentKit-Webhook-Signature` against the raw body before parsing business fields. Payloads must include `event_id` for replay protection. `external_id` is hashed before storage.
|
|
128
|
+
|
|
129
|
+
Evolution WhatsApp uses a self-hosted API key and an AgentKit webhook token:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
whatsappChannel({
|
|
133
|
+
name: "support-whatsapp",
|
|
134
|
+
provider: "evolution",
|
|
135
|
+
secrets: [
|
|
136
|
+
"EVOLUTION_API_BASE_URL",
|
|
137
|
+
"EVOLUTION_API_KEY",
|
|
138
|
+
"EVOLUTION_INSTANCE_NAME",
|
|
139
|
+
"EVOLUTION_WEBHOOK_TOKEN",
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
AgentKit configures Evolution's webhook URL with `?token=<EVOLUTION_WEBHOOK_TOKEN>`, validates the token on ingress, redacts Evolution secret values, and rejects unsafe Evolution API base URLs before sending messages or downloading audio media.
|
|
145
|
+
|
|
115
146
|
## Verification
|
|
116
147
|
|
|
117
148
|
```sh
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Connect WhatsApp Through Evolution API
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Connect a self-hosted Evolution API WhatsApp instance to a hosted AgentKit WhatsApp channel.
|
|
6
|
+
|
|
7
|
+
## When To Use It
|
|
8
|
+
|
|
9
|
+
Use this after `whatsappChannel({ name: "main-whatsapp", provider: "evolution" })` exists in `agentkit.config.ts` and the capsule has been deployed.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
agentkit deploy
|
|
15
|
+
agentkit channels connect whatsapp main-whatsapp --provider evolution
|
|
16
|
+
agentkit channels status main-whatsapp
|
|
17
|
+
agentkit channels test main-whatsapp --message "hello"
|
|
18
|
+
agentkit channels deliveries list main-whatsapp
|
|
19
|
+
agentkit channels buffers list main-whatsapp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Required secrets:
|
|
23
|
+
|
|
24
|
+
```txt
|
|
25
|
+
EVOLUTION_API_BASE_URL
|
|
26
|
+
EVOLUTION_API_KEY
|
|
27
|
+
EVOLUTION_INSTANCE_NAME
|
|
28
|
+
EVOLUTION_WEBHOOK_TOKEN
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If WhatsApp audio transcription is enabled, also set the transcription provider secret declared by `agentkit inspect`, usually `OPENAI_API_KEY` or `GROQ_API_KEY`.
|
|
32
|
+
|
|
33
|
+
## Minimal Working Example
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { defineAgent, whatsappChannel } from "@andreprado/agentkit";
|
|
37
|
+
|
|
38
|
+
export default defineAgent({
|
|
39
|
+
name: "my-agent",
|
|
40
|
+
runtime: "edge",
|
|
41
|
+
provider: { name: "test", model: "fake" },
|
|
42
|
+
instructions: "./prompts/instructions.md",
|
|
43
|
+
secrets: [],
|
|
44
|
+
tools: [],
|
|
45
|
+
channels: [whatsappChannel({ name: "main-whatsapp", provider: "evolution" })],
|
|
46
|
+
access: { mode: "public" },
|
|
47
|
+
storage: { driver: "agentkit" },
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Setup Behavior
|
|
52
|
+
|
|
53
|
+
`agentkit channels connect whatsapp main-whatsapp --provider evolution` creates or updates the hosted channel, verifies managed secrets, calls Evolution API `POST /webhook/set/{instance}`, confirms the configured webhook through `GET /webhook/find/{instance}`, then runs a synthetic inbound smoke.
|
|
54
|
+
|
|
55
|
+
Expected webhook URL shape:
|
|
56
|
+
|
|
57
|
+
```txt
|
|
58
|
+
https://<deploy-host>/channels/main-whatsapp/whatsapp/evolution/webhook
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
AgentKit registers the webhook URL with the required token query parameter:
|
|
62
|
+
|
|
63
|
+
```txt
|
|
64
|
+
https://<deploy-host>/channels/main-whatsapp/whatsapp/evolution/webhook?token=<EVOLUTION_WEBHOOK_TOKEN>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`EVOLUTION_API_BASE_URL` must be the public HTTPS origin for the Evolution API server, for example `https://evolution.example.com`. AgentKit rejects HTTP, localhost, private-network, link-local, metadata, and credential-bearing base URLs before sending `EVOLUTION_API_KEY`.
|
|
68
|
+
|
|
69
|
+
## Audio
|
|
70
|
+
|
|
71
|
+
Use `transcription` at the agent level and `audio.mode: "transcribe"` on the Evolution channel.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
whatsappChannel({
|
|
75
|
+
name: "main-whatsapp",
|
|
76
|
+
provider: "evolution",
|
|
77
|
+
audio: {
|
|
78
|
+
mode: "transcribe",
|
|
79
|
+
},
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Evolution audio webhooks become normalized audio messages. The retryable channel worker downloads media through Evolution API `POST /chat/getBase64FromMediaMessage/{instance}` and sends the bytes to AgentKit's configured transcription provider.
|
|
84
|
+
|
|
85
|
+
## Safety Rules
|
|
86
|
+
|
|
87
|
+
- Keep phone numbers redacted in logs by default.
|
|
88
|
+
- Do not store Evolution API keys or webhook tokens in `agentkit.config.ts`.
|
|
89
|
+
- `EVOLUTION_WEBHOOK_TOKEN` is required because AgentKit V1 does not rely on an Evolution webhook body-signature contract.
|
|
90
|
+
- AgentKit ignores `fromMe` messages to avoid reply loops.
|
|
91
|
+
- Text replies call Evolution API `POST /message/sendText/{instance}` with the `apikey` header and a body containing `number` and `text`.
|
|
92
|
+
- Real provider success is recorded as `provider_sent` only when Evolution returns a provider message id.
|
|
93
|
+
- Only set `AGENTKIT_CHANNEL_SEND_DRY_RUN=1` in tests when Evolution should not receive a real message. Dry-run deliveries are recorded as `adapter_stubbed`, not sent.
|
|
94
|
+
|
|
95
|
+
## Verification
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
agentkit channels setup main-whatsapp --apply
|
|
99
|
+
agentkit channels status main-whatsapp
|
|
100
|
+
agentkit channels test main-whatsapp --message "hello"
|
|
101
|
+
agentkit channels test-audio main-whatsapp --fixture voice-note
|
|
102
|
+
agentkit channels deliveries list main-whatsapp
|
|
103
|
+
agentkit channels deliveries show <delivery-id>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Troubleshooting
|
|
107
|
+
|
|
108
|
+
`channel_secret_missing`:
|
|
109
|
+
Set `EVOLUTION_API_BASE_URL`, `EVOLUTION_API_KEY`, `EVOLUTION_INSTANCE_NAME`, and `EVOLUTION_WEBHOOK_TOKEN` as hosted managed secrets.
|
|
110
|
+
|
|
111
|
+
`channel_signature_invalid`:
|
|
112
|
+
The Evolution webhook query token does not match.
|
|
113
|
+
|
|
114
|
+
`channel_provider_setup_invalid`:
|
|
115
|
+
`EVOLUTION_API_BASE_URL` is not an allowed public HTTPS base URL.
|
|
116
|
+
|
|
117
|
+
`channel_provider_setup_failed`:
|
|
118
|
+
AgentKit could not configure or verify the Evolution webhook through `/webhook/set/{instance}` and `/webhook/find/{instance}`.
|
|
119
|
+
|
|
120
|
+
`channel_audio_download_unavailable`:
|
|
121
|
+
Evolution did not return base64 media data from `/chat/getBase64FromMediaMessage/{instance}`, or the audio payload did not include a provider message id.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Connect WhatsApp Through UAZAPI
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Connect a UAZAPI WhatsApp instance to a hosted AgentKit WhatsApp channel.
|
|
6
|
+
|
|
7
|
+
## When To Use It
|
|
8
|
+
|
|
9
|
+
Use this after `whatsappChannel({ name: "support-whatsapp", provider: "uazapi" })` exists in `agentkit.config.ts` and the capsule has been deployed.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
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
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Required secrets:
|
|
23
|
+
|
|
24
|
+
```txt
|
|
25
|
+
UAZAPI_BASE_URL
|
|
26
|
+
UAZAPI_TOKEN
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Optional hardening secret:
|
|
30
|
+
|
|
31
|
+
```txt
|
|
32
|
+
UAZAPI_WEBHOOK_TOKEN
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If WhatsApp audio transcription is enabled, also set the transcription provider secret declared by `agentkit inspect`, usually `OPENAI_API_KEY` or `GROQ_API_KEY`.
|
|
36
|
+
|
|
37
|
+
## Minimal Working Example
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { defineAgent, whatsappChannel } from "@andreprado/agentkit";
|
|
41
|
+
|
|
42
|
+
export default defineAgent({
|
|
43
|
+
name: "support-agent",
|
|
44
|
+
runtime: "edge",
|
|
45
|
+
provider: { name: "test", model: "fake" },
|
|
46
|
+
instructions: "./prompts/instructions.md",
|
|
47
|
+
secrets: [],
|
|
48
|
+
tools: [],
|
|
49
|
+
channels: [whatsappChannel({ name: "support-whatsapp", provider: "uazapi" })],
|
|
50
|
+
access: { mode: "public" },
|
|
51
|
+
storage: { driver: "agentkit" },
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Setup Behavior
|
|
56
|
+
|
|
57
|
+
`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
|
+
|
|
59
|
+
Expected webhook URL shape:
|
|
60
|
+
|
|
61
|
+
```txt
|
|
62
|
+
https://<deploy-host>/channels/support-whatsapp/whatsapp/uazapi/webhook
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If the channel declares `UAZAPI_WEBHOOK_TOKEN`, AgentKit registers the webhook URL with the token query parameter:
|
|
66
|
+
|
|
67
|
+
```txt
|
|
68
|
+
https://<deploy-host>/channels/support-whatsapp/whatsapp/uazapi/webhook?token=<UAZAPI_WEBHOOK_TOKEN>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`UAZAPI_BASE_URL` must be an HTTPS UAZAPI instance URL, for example `https://api.uazapi.com`. AgentKit rejects localhost, private-network, link-local, metadata, and credential-bearing base URLs before sending `UAZAPI_TOKEN`.
|
|
72
|
+
|
|
73
|
+
## Audio
|
|
74
|
+
|
|
75
|
+
Use `transcription` at the agent level and `audio.mode: "transcribe"` on the UAZAPI channel.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
whatsappChannel({
|
|
79
|
+
name: "support-whatsapp",
|
|
80
|
+
provider: "uazapi",
|
|
81
|
+
audio: {
|
|
82
|
+
mode: "transcribe",
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
UAZAPI audio webhooks become normalized audio messages. The retryable channel worker downloads media through UAZAPI `/message/download` using `return_base64: true`; AgentKit does not fetch arbitrary webhook-provided media URLs.
|
|
88
|
+
|
|
89
|
+
## Safety Rules
|
|
90
|
+
|
|
91
|
+
- Keep phone numbers redacted in logs by default.
|
|
92
|
+
- 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.
|
|
95
|
+
- AgentKit ignores `fromMe` and `wasSentByApi` messages to avoid reply loops.
|
|
96
|
+
- 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
|
+
- Real provider success is recorded as `provider_sent` only when UAZAPI returns a provider message id.
|
|
98
|
+
- Only set `AGENTKIT_CHANNEL_SEND_DRY_RUN=1` in tests when UAZAPI should not receive a real message. Dry-run deliveries are recorded as `adapter_stubbed`, not sent.
|
|
99
|
+
|
|
100
|
+
## Verification
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
agentkit channels setup support-whatsapp --apply
|
|
104
|
+
agentkit channels status support-whatsapp
|
|
105
|
+
agentkit channels test support-whatsapp --message "hello"
|
|
106
|
+
agentkit channels test-audio support-whatsapp --fixture voice-note
|
|
107
|
+
agentkit channels deliveries list support-whatsapp
|
|
108
|
+
agentkit channels deliveries show <delivery-id>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Troubleshooting
|
|
112
|
+
|
|
113
|
+
`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.
|
|
115
|
+
|
|
116
|
+
`channel_signature_invalid`:
|
|
117
|
+
The optional UAZAPI webhook query token does not match.
|
|
118
|
+
|
|
119
|
+
`channel_provider_setup_invalid`:
|
|
120
|
+
`UAZAPI_BASE_URL` is not an allowed HTTPS public base URL.
|
|
121
|
+
|
|
122
|
+
`channel_provider_setup_failed`:
|
|
123
|
+
AgentKit could not configure or verify the UAZAPI webhook through `/webhook`.
|
|
124
|
+
|
|
125
|
+
`channel_audio_download_unavailable`:
|
|
126
|
+
UAZAPI did not return base64 media data from `/message/download`, or the audio payload did not include a provider message id.
|
|
@@ -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
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Goal
|
|
4
4
|
|
|
5
|
-
Diagnose website, Telegram, WhatsApp, Discord, or
|
|
5
|
+
Diagnose website, Telegram, WhatsApp, Discord, Slack, or generic webhook channel setup, webhook validation, dedupe, buffering, outbound sends, and delivery failures from the Agent Capsule CLI.
|
|
6
6
|
|
|
7
7
|
## When To Use It
|
|
8
8
|
|
|
@@ -69,7 +69,7 @@ Expected `show` output includes signature status, dedupe key, queue/run state, o
|
|
|
69
69
|
|
|
70
70
|
- Inspect delivery IDs, hashes, statuses, and redacted metadata rather than raw provider payloads.
|
|
71
71
|
- Never paste provider secrets into fixtures or prompts.
|
|
72
|
-
- Treat `adapter_stubbed` as
|
|
72
|
+
- Treat `adapter_stubbed` as "no outbound provider call happened", not proof that a client received a message. It can mean explicit dry-run mode or an inbound-only channel such as a generic webhook.
|
|
73
73
|
- Before replaying or flushing buffered conversations, confirm the channel name and conversation ID.
|
|
74
74
|
- Keep local `.env` values ignored and upload hosted production values through AgentKit secret commands.
|
|
75
75
|
|
|
@@ -117,7 +117,7 @@ The provider retried an already-processed event. No second agent run should be c
|
|
|
117
117
|
The message is accepted and waiting inside a per-conversation channel buffer. It should move to `queued` after the quiet window, max wait, max message count, or max character count.
|
|
118
118
|
|
|
119
119
|
`adapter_stubbed`:
|
|
120
|
-
The adapter
|
|
120
|
+
The adapter completed without calling an outbound provider. This can happen in explicit dry-run mode or for an inbound-only channel such as a generic webhook.
|
|
121
121
|
|
|
122
122
|
`provider_sent`:
|
|
123
123
|
The provider API accepted the outbound request and returned a provider message ID.
|
|
@@ -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
|
|