Build your first bot
This is the whole product in one page. By the end you will have created a chatbot, given it something to read, waited for it to finish learning, and asked it a question that it answers from your content.
Everything here uses a test key (agy_test_…), so nothing you do costs
live credits. Swap in a live key when you are happy.
An API key with `chatbots:write`, `knowledge:write` and `chat:send`. Mint one
in the dashboard under Developers → API keys, and copy the secret — it is
shown once.
The shape of the thing
Four calls, in order. Each one is ordinary REST; the only unusual part is step three, because training is asynchronous.
- Create a chatbot. You get an id back.
- Attach knowledge to it — a page, a document, or raw text.
- Wait for training to finish. Poll, or let a webhook tell you.
- Send a message and read the answer.
Step 1 — Create the chatbot
A chatbot is the unit everything else hangs off: knowledge belongs to one, conversations happen with one, and actions are registered against one.
Only name is required. primary_language takes a language name (English,
Arabic, Spanish, …) and defaults to English; the header colours and
response length default to the platform theme when omitted.
POST/v1/chatbots
curl -X POST https://api.agentency.com/v1/chatbots \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: first-bot-0001" \
-d '{
"name": "Support Assistant",
"description": "Answers billing and shipping questions.",
"primary_language": "English"
}'You get the full chatbot object back. Keep id — every later call needs it.
{
"object": "chatbot",
"id": 1,
"name": "Support Assistant",
"status": "draft",
"training_status": "never_trained",
"created_at": "2026-01-01T00:00:00+00:00"
}Note the `Idempotency-Key`. If this request times out and you retry it with the same key, you get the original chatbot back instead of a second one. Use a new key for a genuinely new bot.
Step 2 — Give it something to read
Knowledge is attached per chatbot. The quickest source is a URL: point it at a page and the crawler fetches and extracts the text for you.
POST/v1/knowledge
curl -X POST https://api.agentency.com/v1/knowledge \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json" \
-d '{
"chatbot_id": 1,
"name": "Refund policy",
"type": "URL",
"source_type": "url",
"source_url": "https://example.com/refunds",
"auto_train": true
}'auto_train: true means training starts immediately. Leave it off if you want
to attach several sources first and train once.
To upload a file instead, POST /v1/files and pass the returned file_id to
POST /v1/knowledge with source_type: "upload". You can send several files
in one request as files[].
Step 3 — Wait for training
This is the step people get wrong. Creating knowledge returns immediately; the bot cannot answer from it until embedding finishes. There are two ways to know when that is.
Poll the status
Cheap and obvious. Ask the dataset how it is doing until it reaches a terminal state.
GET/v1/knowledge/{id}/status
curl https://api.agentency.com/v1/knowledge/1/status \
-H "Authorization: Bearer <YOUR_KEY>"embedding_status moves not_started → pending → processing →
completed, or failed. Poll every few seconds; a short page takes seconds, a
large document takes longer.
To ask about the whole bot rather than one source, use
GET /v1/chatbots/{id}/readiness, which tells you whether it has enough
trained knowledge to answer at all.
Or let a webhook tell you
Better for anything long-running: register an endpoint once and stop polling.
Subscribe to `knowledge.dataset.trained` and `knowledge.dataset.failed`. You get told the moment a source is usable, and you find out about failures instead of watching a status field stay stuck.
Step 4 — Ask it something
POST/v1/chat
curl -X POST https://api.agentency.com/v1/chat \
-H "Authorization: Bearer <YOUR_KEY>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: first-turn-0001" \
-d '{
"chatbot_id": 1,
"message": "How long do refunds take?"
}'The answer comes back with the text, the sources it used, and the ids you need to continue the conversation:
{
"object": "message",
"id": 1,
"conversation_id": 1,
"session_id": "api_9f2c…",
"response": "Refunds are issued to the original payment method within 5 business days.",
"sources": [{ "title": "Refund policy", "dataset_id": 1 }],
"usage": { "input_tokens": 33, "output_tokens": 157 },
"confidence_score": 92.4
}To continue the same conversation, send session_id back on the next call.
Leave it out and you start a fresh one.
Always send an `Idempotency-Key` on `POST /v1/chat` and `/v1/chat/stream`. A network timeout followed by a blind retry is otherwise two billed turns.
When the answer is wrong
Two things worth checking before assuming the model is at fault.
sourcesis empty. Nothing relevant was retrieved, so the bot answered from general knowledge or declined. Usually the content has not finished training, or it does not actually contain the answer.confidence_scoreis low. It found something but was not sure. Adding a more specific source usually fixes it faster than rewording the prompt.
What's next
- Train a bot — every knowledge source type, and how re-training works.
- Chat — streaming, conversation continuity, citations.
- Actions — let the bot call your own systems.
- Going live — the checklist before you switch to a live key.