Skip to main content

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.
curl -X POST https://api.orbit.devotel.io/api/v1/agents \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support Agent",
    "description": "Handles customer support inquiries for Acme Corp",
    "model": "claude-sonnet-4-6",
    "system_prompt": "You are a customer support agent for Acme Corp. Be helpful, concise, and professional. If you cannot resolve an issue, offer to transfer to a human agent.",
    "temperature": 0.3
  }'

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 the tools 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/tools for the catalog).
  • A function-call object with name, description, and a JSON-Schema parameters object — the standard function-calling contract the model receives.
curl -X PATCH https://api.orbit.devotel.io/api/v1/agents/agent_abc123 \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "tools": [
      "knowledge_base",
      "human_handoff",
      {
        "name": "lookup_order",
        "description": "Look up an order by order ID or customer email",
        "parameters": {
          "type": "object",
          "properties": {
            "order_id": { "type": "string", "description": "The order ID" },
            "email": { "type": "string", "description": "Customer email address" }
          }
        }
      }
    ]
  }'
The same 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’s tools array.
curl -X POST https://api.orbit.devotel.io/api/v1/agents/custom-tools \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "lookup_order",
    "description": "Look up an order by order ID or customer email",
    "json_schema": {
      "type": "object",
      "properties": {
        "order_id": { "type": "string", "description": "The order ID" },
        "email": { "type": "string", "description": "Customer email address" }
      }
    },
    "executor_url": "https://api.acme.com/orders/search",
    "executor_secret": "whsec_...",
    "confirmation": "never"
  }'
Once registered, add the tool to an agent by its name in the tools array (e.g. "tools": ["lookup_order"]).

Built-in Tools

Orbit provides several built-in tools that agents can use out of the box. The authoritative list is returned live by GET /api/v1/agents/tools:
Tool IDNameDescription
send_smsSend SMSSend an SMS message via Devotel
send_whatsappSend WhatsAppSend a WhatsApp message
send_emailSend EmailCompose and send email
lookup_contactLook up contactSearch contact directory
check_balanceCheck balanceRetrieve account balance
create_ticketCreate ticketOpen a support ticket
search_knowledgeSearch knowledge baseSemantic search across documents
transfer_agentTransfer to humanEscalate to live agent
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

curl -X POST https://api.orbit.devotel.io/api/v1/knowledge-bases \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Support Docs",
    "description": "FAQs and policies for the support agent"
  }'
The response includes the new KB’s 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. The file part is required; type is optional and inferred from the file extension when omitted.
curl -X POST https://api.orbit.devotel.io/api/v1/knowledge-bases/kb_xyz789/documents \
  -H "X-API-Key: dv_live_sk_..." \
  -F "file=@faq.pdf"
Orbit chunks, embeds, and indexes documents in Qdrant for fast retrieval. Embeddings are handled by Orbit’s internal pipeline — you don’t manage embedding API keys. Attach one or more KBs to the agent with the knowledge_base_ids array on create or update. IDs are validated against your tenant — an unknown ID returns 422 INVALID_KNOWLEDGE_BASE_IDS.
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/agent_abc123 \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "knowledge_base_ids": ["kb_xyz789"]
  }'

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. Send safety_config and escalation_triggers on the create (POST /agents) or update (PUT /agents/:id) body.
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/agent_abc123 \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "safety_config": {
      "pii_redaction": true,
      "pii_detection": true,
      "content_filter": true,
      "harmful_content": true,
      "prompt_injection": true,
      "blocked_topics": ["competitor pricing", "internal processes"],
      "max_response_length": 2000,
      "approval_required": false
    },
    "escalation_triggers": [
      { "type": "keyword", "value": "speak to human" },
      { "type": "keyword", "value": "manager" },
      { "type": "keyword", "value": "complaint" },
      { "type": "turn_count_above", "value": 50 },
      { "type": "sentiment_below", "value": 0.3 }
    ]
  }'
safety_config accepts: blocked_topics, max_response_length, content_policy, pii_redaction, pii_detection, 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": <1–100> } (replacing the old flat escalation_keywords / max_turns fields).

Step 5: Deploy

Deploying is how you bind an agent to a channel — there is no channels 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. Supply phone_number for the phone-backed channels (sms, whatsapp, voice, rcs) and webhook_url for the webhook channel. Deploy to WhatsApp:
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/deploy \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "whatsapp",
    "phone_number": "+18005551234"
  }'
Deploy to the webhook channel (provide webhook_url so Orbit can post agent events to your endpoint — it must be an https:// URL):
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/deploy \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "webhook",
    "webhook_url": "https://api.acme.com/orbit/agent-events"
  }'
To go live on multiple channels (for example SMS, voice, and RCS), repeat the call once per channel:
# SMS
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/deploy \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "channel": "sms", "phone_number": "+18005551234" }'

# Voice
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/deploy \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "channel": "voice", "phone_number": "+18005551234" }'

# RCS
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/deploy \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "channel": "rcs", "phone_number": "+18005551234" }'

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):
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/dry-run \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "scenario": {
      "turns": [
        { "user_msg": "Hi, I need help with order ORD-12345" }
      ]
    }
  }'
The dry-run response returns a turn-by-turn trace and (optionally) an assertion verdict — supply 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:
curl -X POST https://api.orbit.devotel.io/api/v1/agents/agent_abc123/chat \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Hi, I need help with order ORD-12345"
  }'