Creating Agents
This guide walks you through creating, configuring, and deploying an AI agent on Orbit — from defining its behavior to connecting it to live channels.Step 1: Define the Agent
Create an agent with a name, instructions, and model selection.Step 2: Add Tools
Tools give your agent the ability to take actions — look up orders, create tickets, check inventory, etc. There is no separate “add tool” endpoint. Tools are configured through thetools array on the agent’s create or update body. Each entry is one of:
- A string referencing a built-in or registered tool by id (see
GET /agents/toolsfor the catalog). - A function-call object with
name,description, and a JSON-Schemaparametersobject — the standard function-calling contract the model receives.
tools array is accepted on POST /api/v1/agents at create time. A function-call entry tells the model the tool’s shape but does not, by itself, perform an outbound HTTP call.
Reusable HTTP tools (custom tools)
To register a reusable tool that calls an external HTTP endpoint, use the custom-tools surface. Custom tools are tenant-scoped, SSRF-validated, and can be referenced by name from any agent’stools array.
name in the tools array (e.g. "tools": ["lookup_order"]).
Managing custom tools
Beyond create, the custom-tools surface is a full CRUD API rooted at/api/v1/agents/custom-tools. Every endpoint is tenant-scoped and requires the owner, admin, or developer role for writes.
A custom tool is returned in this shape. The plaintext executor_secret is never echoed back — executor_secret_set reports whether one is stored:
{ "tools": [...], "total": <count> }.
Get a single custom tool
404 NOT_FOUND if the tool does not exist in your tenant.
Update a custom tool
PATCH applies a partial update — send only the fields you want to change. Accepts description, json_schema, executor_url, executor_secret, enabled, timeout_ms, and confirmation. For executor_secret: send a new value to rotate it, send null to clear it, or omit it to leave it unchanged. A changed executor_url is re-validated against the SSRF rules before it is saved.
{ "id": "tool_abc123", "deleted": true }.
Test a custom tool (dry run)
Fire a one-off request at the tool’s executor_url with sample args to confirm it is wired up correctly. This never persists anything and forwards the live response back to you. Optionally override the URL, secret, or timeout to test an unsaved change without first updating the tool.
ok is false, error carries a short reason (for example a timeout or an HTTP 500 from your endpoint), and status is the HTTP status your executor returned (or 0 when no response was received).
Built-in Tools
Orbit provides several built-in tools that agents can use out of the box. The authoritative list is returned live byGET /api/v1/agents/tools:
Reference a built-in tool by its ID in the
tools array when creating an agent
(for example, "tools": ["search_knowledge"]). To ground search_knowledge in
your own content, attach documents via knowledge_base_ids (see Step 3).
Step 3: Connect Knowledge Base
Knowledge lives in a knowledge base (KB) — a reusable container of documents that you create once and then link to one or more agents. There is no per-agent upload endpoint; instead you create a KB, upload documents to it, and attach the KB to the agent by ID.3a. Create a knowledge base
id (e.g. kb_xyz789). Use it in the next two steps.
3b. Upload documents
Upload each document to the KB with a multipart request. Thefile part is required; type is optional and inferred from the file extension when omitted.
3c. Link the knowledge base to the agent
Attach one or more KBs to the agent with theknowledge_base_ids array on create or update. IDs are validated against your tenant — an unknown ID returns 422 INVALID_KNOWLEDGE_BASE_IDS.
Step 4: Configure Guardrails
Set safety boundaries for your agent’s behavior. Guardrails are part of the agent itself — there is no separate guardrails endpoint. Sendsafety_config and
escalation_triggers on the create (POST /agents) or update (PUT /agents/:id)
body.
safety_config accepts: blocked_topics, max_response_length, content_policy,
pii_redaction, pii_detection, pii_egress, sensitive_words,
harmful_content, prompt_injection, content_filter, and approval_required. Each
escalation_triggers entry is one of { "type": "keyword", "value": "<string>" },
{ "type": "sentiment_below", "value": <0–1> }, or
{ "type": "turn_count_above", "value": <positive integer> } (replacing the old flat
escalation_keywords / max_turns fields).
Keeping PII out of tool calls (pii_egress)
The output-side guardrails (pii_redaction / pii_detection) scrub what the
agent says back and what a tool returns. They do not cover what the
agent sends out through a tool. Tools dispatch arguments the model composed
— a message like “email my records to me@example.com” or “text +1 555 123 4567
my balance” can put PII straight into the body of a webhook or custom-tool
call, and that payload leaves Orbit through the connector even when every
inbound/outbound text guard is on.
Set safety_config.pii_egress: true on an agent to scrub every tool call’s
arguments at the dispatch boundary, before the connector sees them. The guard:
- Scans the universal PII floor (email, phone, SSN, payment card) inside every
string value in the arguments — at any nesting depth — and substitutes
[REDACTED]. Keys, numbers, booleans, and the JSON structure of the arguments are preserved, so the connector receives the same shape minus the PII. - Layers any
locale_pii_patternscodes the agent already opted into on top of the universal floor — the egress guard scans with the same coverage the output side uses. - Is off by default. Turn it on per agent whose tool surface tolerates
redacted text — webhook and custom-tool connectors are the norm. Leave it
off for agents whose tools parse a value as a strict identifier (for example
send_smsparses itstofield as an E.164 number;[REDACTED]there would fail the dispatch).
Scrubbing specific literal words (sensitive_words)
Where blocked_topics refuses whole subject areas, sensitive_words scrubs a
literal word or phrase list from the agent’s output — every match is
replaced inline with [REDACTED] before the turn is returned (LOW severity:
advisory, not blocking). Use it for competitor names, internal codenames, or
any term the agent should never speak. Matching is literal and
case-insensitive with word-boundary edges; a hard block stays the job of
blocked_topics / harmful_content. Full semantics and a worked example are
on the Sensitive words guardrail page.
Step 5: Deploy
Deploying is how you bind an agent to a channel — there is nochannels field on the agent itself, and channels are never assigned on the create or update body. Activate your agent to start handling live conversations. Each deploy call targets one channel, so call the endpoint once per channel you want to go live on.
The request body requires a channel field — one of webhook, sms, whatsapp, voice, or rcs. A bodyless POST is rejected with 422 Unprocessable Entity. phone_number is required when channel is voice and optional for the other phone-backed channels (sms, whatsapp, rcs); supply webhook_url for the webhook channel.
Deploy to WhatsApp:
webhook channel (provide webhook_url so Orbit can post agent events to your endpoint — it must be an https:// URL):
Testing
Test your agent before going live without sending real messages or incurring channel/outbound costs. Use the dry-run endpoint to replay a scripted scenario in sandbox mode — mutative tools are short-circuited and no live side effects occur (note: the agent still calls the LLM, so model/token cost applies):expected_tool_calls, must_contain, or must_not_contain
inside scenario to gate the run.
For an interactive single-turn test against the live agent runtime, use the
chat endpoint instead. This is a real turn — it incurs LLM cost — but it is
not channel-routed, so no outbound message is sent: