Roxels/ docs
templates

Data sources

A data source is a live API the agent can call mid-conversation to look something up. Customers by name. Products by SKU. A user's order history. The current weather, if the conversation calls for it.

Data sources are how the agent stays grounded in your real data without you having to pre-load everything into the conversation context.

When to use them

You want a data source when:

  • The agent needs to resolve a user's free-form mention into a real identifier ("Is this the Acme order from last Tuesday or the one from this morning?").
  • The conversation adapts based on something the agent has to look up ("Their plan is Pro, so offer the Pro-tier walkthrough").
  • The agent might mention specific entities by canonical name rather than the user's wording.

You don't want a data source when:

  • The context can just be passed in at session creation — that's what the conversation context is for.
  • You only need the data after the conversation ends — use a webhook instead.

How they work

You declare a data source in the template:

{
  "settings": {
    "data_sources": [
      {
        "id": "lookup_customer",
        "name": "Lookup customer",
        "description": "Search the customer database by name, email, or phone.",
        "endpoint": "https://api.example.com/customers/search",
        "method": "GET",
        "params": [{ "name": "q", "description": "Search query — name, email, or phone." }],
        "headers": {
          "Authorization": "Bearer {{secret:my-api-key}}"
        },
        "response_shape": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "name": { "type": "string" },
              "plan": { "type": "string" }
            }
          }
        }
      }
    ]
  }
}

The agent now has access to lookup_customer as a tool. When the conversation calls for it ("the user said they're 'Sarah from Acme'") the agent calls the data source with the right arguments, parses the response, and uses the result in the conversation.

Anatomy of a data source

Field Description
id Stable identifier. Referenced in goals, outputs, or other data sources.
name Human-readable name. Shown in the dashboard.
description Tells the agent when to call this data source. The agent reads it to decide whether the current situation matches.
endpoint URL to call. Supports {{context.*}} and {{secret:*}} interpolation.
method HTTP method. Defaults to GET.
params Parameters the agent can pass. Each has a name and description (the description tells the agent what to put there).
headers Static headers. Use {{secret:*}} for tokens.
response_shape JSON Schema describing the response. The agent uses this to know what to read out of the response.

The description field on the data source and on each param is the most important — it's how the LLM decides whether to use this data source and what arguments to send.

Resolving identifiers

A common use is ID resolution: the user says a name; the agent needs the canonical id.

{
  "id": "resolve_customer_id",
  "name": "Resolve customer id",
  "description": "Use this to look up a customer's canonical id from a name or email mentioned in conversation.",
  "endpoint": "https://api.example.com/customers/search",
  "method": "GET",
  "params": [{ "name": "q", "description": "The customer's name, email, or partial mention." }],
  "response_shape": {
    "type": "array",
    "items": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "name": { "type": "string" }
      }
    }
  }
}

When the user says "Sarah from Acme," the agent calls resolve_customer_id?q=Sarah%20Acme, sees the candidates in the response, and either picks the unambiguous one or asks the user to clarify ("I see two — Sarah Lee at Acme Industries and Sarah Park at Acme Co. Which one?").

This is the safe path for downstream systems that expect canonical ids in webhook payloads.

Using results in extraction

When a data source returns a value, the agent can commit it as part of a goal. If your goal's schema expects customer_id: string, and resolve_customer_id returned {"id": "cus_abc"}, the agent commits customer_id: "cus_abc".

This is much better than the agent guessing at an id format — the resolution call is the source of truth.

Authentication

Use the Roxels secret store for any tokens:

{
  "headers": {
    "Authorization": "Bearer {{secret:abc-uuid}}"
  }
}

The secret value is swapped in at call time and never appears in the template config. See Webhooks overview § secrets for how the secret store works (same store for both surfaces).

Errors and fallbacks

When a data source call fails:

  • The agent sees the error.
  • The agent does not retry blindly — it adapts ("I'm having trouble finding that — could you spell their email for me?").
  • Failures are logged and surfaced as learnings on the template.

If your endpoint returns a 4xx with a helpful message, include the message in the response body — the agent uses it to decide what to say next.

Patterns

Live customer lookup

Use case: a support conversation where the agent must know who the user is.

  1. Data source: lookup_customer (search by name/email).
  2. The agent calls it when the user identifies themselves.
  3. The agent uses the result throughout the rest of the conversation.

Product catalog

Use case: a sales conversation where the agent must reference real products.

  1. Data source: search_products (full-text search).
  2. The agent calls it when the user describes what they're looking for.
  3. The agent quotes real SKUs, prices, and availability.

Tiered fallback (search → grep → ask)

For tricky resolutions, declare two data sources:

  1. resolve_strict — exact match by id or email.
  2. search_loose — fuzzy search by name.

The agent tries strict first; if no result, falls back to loose; if still ambiguous, asks the user.