Skip to content

Agents and skills

This page configures three linked concepts: agents, the directives that steer them turn by turn, and the named skills an agent can use from routines or supported invocation modes. The read-only product skills catalog still describes stable platform contracts. The host that issued your workspace token is the host these routes answer on — see Workspaces and tokens.

Authoring and execution are different. Agent skills are created through the agent skill endpoints. Runtime still dispatches through the capability executor behind the named skill.

Agents

Each workspace has a default agent. Chat calls use that agent when agentId is omitted.

Agents own:

  • display name and logo
  • custom instructions
  • suggested-question behavior on the default retrieve skill
  • theme and greeting behavior
  • source scope
  • surface settings for authenticated chat, anonymous chat, and website embed

Retrieval answer configuration lives on the agent’s default-answer retrieve skill. Use the unified skill endpoints to update fields such as query rewrite behavior, reranking, metadata rules, strategy, source scope, suggested questions, and answer instruction for that one agent.

The read-only GET /api/v1/settings/retrieval-defaults endpoint returns those inherited retrieval defaults plus workspace metadata field suggestions for the Skills tab. It does not update retrieval behavior.

If an agent has retrievalEnabled: true, assistant chat may use retrieval and return citations. If retrievalEnabled: false, the agent answers through the direct assistant path and returns diagnostics with retrievalInvoked: false.

Directives

Directives add steering to matching turns. A directive has a condition, an action, optional priority and relationship fields, and optional scope tags.

In the dashboard you author directives in the agent’s Directives settings, where your own rules sit above the built-in Radioso directives you can Override.

The dashboard Directives screen with an authored directive "Shipping delay empathy" above the read-only built-in directives, each with an Override button.

Create a directive with POST /api/v1/agents/{agentId}/directives:

json
{
  "name": "order-status",
  "condition": {
    "kind": "contextual",
    "description": "the visitor asks about an order status"
  },
  "action": "Look up the order before answering. Do not guess order state.",
  "priority": 80,
  "binding": {
    "kind": "skill",
    "skillName": "order_lookup"
  }
}

binding is optional and may be null. The only supported binding kind is skill. The named skill must exist on the agent, be enabled, and use agent_selectable invocation mode. External MCP skills (kind: external_mcp) can claim the terminal turn and produce a user-facing chat reply. Retrieval skills (kind: retrieve) are staged into the agentic retrieval loop as directive-scoped lookup tools. Action-only skill kinds are rejected. Invalid bindings return 400 and name the offending skill.

In the dashboard, the binding is a chip in the directive’s Instruction field: type # to pick from the skills this agent can bind, and the chip you insert is binding.skillName. The menu offers exactly the skills the API accepts, and a directive holds one, so the menu explains itself instead of offering a second while a chip is present. Deleting the chip clears the binding on save. A binding whose skill is disabled or renamed keeps its chip and marks it as an unknown skill, so the rule stays visible instead of disappearing.

The chip is the binding, and binding in the API is what decides which text is a chip when the directive is opened again. Prose reads as prose: an action such as Point the customer at #billing for pricing questions. on a directive with no binding keeps those characters as words, and saving the directive leaves binding at null — even when a bindable skill named billing exists.

Write the chip wherever the sentence needs it, including at the end: Escalate using #issue_refund. binds issue_refund and keeps its period, because a trailing . , ; : ! or ? belongs to the prose. Reopening that directive shows the same chip and the same text, so a save that changes only the priority sends the action back unchanged.

If you type a name the agent has no skill for, the menu offers Create skill ”…”. That opens the same capability picker and configuration form the Skills list uses, narrowed to the two capabilities a directive can bind — MCP tool and Knowledge retrieval — with the name you typed already in the form. Skill names are lowercase identifiers, so RefundLookup is saved as refundlookup and the chip carries that. The skill is created enabled and agent_selectable, which is what the binding requires. Cancel out of either dialog and the field keeps your prose with no chip and no binding. MCP connections are still set up in the MCP channel section: connecting and authorizing a server is infrastructure, separate from authoring behavior over it.

When a directive with an external MCP binding matches a non-routine turn, the turn selector routes to the bound skill if that skill is available as a runtime turn skill. When a directive with a retrieval binding matches, the answer loop receives a lookup tool for that skill. The directive action still steers the answer. A non-matching directive has no selection effect.

When multiple matched directives bind skills, one binding wins:

  1. higher priority
  2. higher matcher confidence, with deterministic always matches treated as 1.0
  3. directive name ascending

If a bound external MCP skill is later disabled, removed, no longer turn-selectable, not registered at runtime, or blocked by the workspace capability policy (external skills require the external_skills.invoke capability), Radioso ignores the binding and falls through to normal selection. The directive action still applies. The turn trace records selected, losing, and skipped terminal bindings with their reasons. If a bound retrieval skill is unavailable or blocked by the retrieval.answer capability, it is not staged as an agentic lookup tool.

Agent config export/import preserves directive bindings by skill name. Import does not validate that the target agent currently has the skill: when the imported binding points at a skill the agent doesn’t have, the same fall-through rule above applies — Radioso ignores the binding and uses normal selection — right up until you add and enable a skill with that name.

Bindings on directives scoped with routine:<id> or step:<routineId>:<stepId> are accepted but inert during routine turns, because routine flow bypasses terminal turn selection.

Agent skills

GET /api/v1/agents/{agentId}/skill-capabilities returns the capability registry projection for the agent. Each capability includes its targets, whether it requires a target, input schema, outcomes, supported invocation modes, and availability.

GET /api/v1/agents/{agentId}/skills returns the agent’s named skills in one envelope:

  • name
  • capability
  • target
  • config
  • invocationMode
  • enabled

Create skills with POST /api/v1/agents/{agentId}/skills. In the dashboard, Add new skill first opens a capability picker; enabled tiles then open the configuration form for that capability. The form shows only the skill name, enabled state, required target or tool fields, and essential capability settings by default. Invocation mode and advanced retrieval tuning live under Advanced. Input binding, outcomes, and advanced JSON live under Routine integration because they only matter when a routine or the agent selects the skill. The form and API use the same model for retrieve, mcp_tool, email, slack_post, webhook_call, and notify.

A mcp_tool skill (and the external_mcp directive binding below) is Radioso calling out to someone else’s MCP server as a tool. That’s the opposite direction from Radioso’s own MCP server, which a client like Cursor or Claude Desktop connects into.

Each row in the Skills list says which authored surfaces reach it — “Used by 2 directives and 1 routine”, or “Not used by a directive or routine”. A skill nothing references never fires, and the count is the fastest way to spot one after a rename or a deleted directive. The dashboard derives it from GET /api/v1/agents/{agentId}/directives and GET /api/v1/agents/{agentId}/routines; the skill envelope itself carries no usage field. A routine counts once however many of its steps call the skill, and a routine being revised counts once across its draft and published versions.

Update skills with PATCH /api/v1/agents/{agentId}/skills/{skillId}. Use config for a shallow merge into the existing skill config. Use replaceConfig when sending the complete config from an editor and omitted keys should be removed, such as clearing a retrieval override so the skill inherits the default again. Do not send both fields in the same request.

Retrieval skill settings

The retrieve capability descriptor includes field help, inherited defaults, and dependency hints. In the dashboard, an unset field shows the effective system default inline. Saving still stores only overrides. Clearing a field removes that key from the skill config so the agent inherits the system default again.

The main tuning fields are:

  • retrievalStrategy: fixed runs one search pass, reasoning lets the model plan and run multiple searches, and auto lets Radioso choose per query.
  • vectorTopK: how many chunks are fetched from the vector index before filtering and reranking.
  • rerankEnabled: whether the fetched chunks are re-scored with the reranker model. Off by default because it adds a model call to every retrieval.
  • rerankTopK: how many chunks survive reranking and are passed to the answer. It is relevant when reranking is enabled.
  • queryRewriteEnabled: whether the user message is rewritten into search queries before retrieval.
  • semanticRewriteInstructions: the instructions used to rewrite the user message into the semantic vector search query. A non-empty value replaces the default. The dashboard shows the default read-only until you choose Override, which copies it into the editor so you can adjust it. It is relevant when query rewrite is enabled.
  • lexicalRewriteInstructions: the instructions used to rewrite the user message into the lexical keyword search query. It behaves the same way as the semantic instructions. It is relevant when query rewrite is enabled.
  • suggestedQuestionsEnabled: whether the assistant offers follow-up question suggestions after each answer.
  • suggestedQuestionsCount: how many follow-up questions to suggest. It is relevant when suggested questions are enabled.

Context variables

Context variables are workspace declarations that an agent may enable per agent. They are separate from skills. A skill is something the assistant can do; a context variable is data the turn may resolve and use.

The catalog endpoints create and update host-defined variable declarations:

  • name
  • description
  • valueType: string or json
  • trustTier: unverified or signed
  • sensitivity: normal or sensitive
  • defaultSurfacing: always, on_reference, or operator_only

The per-agent enablement endpoints choose how a catalog variable is wired for one agent:

  • source: pushed or resolver
  • surfacing: always, on_reference, or operator_only
  • enabled

The dashboard exposes the pushed source. Resolver-backed variables are part of the API contract; the operator UI does not configure them.

Host backends push runtime values through PUT /api/v1/context-variables/{id}/values. The request identifies the scope:

json
{
  "scope": { "type": "session", "id": "public-session-id" },
  "data": {
    "items": [{ "sku": "course-101", "quantity": 1 }]
  }
}

Values resolve from most specific to least specific scope: session, customer, agent, then workspace. Use the narrowest scope that matches the data. For example, a cart usually belongs to a session or customer; a market-wide promotion may belong to an agent or workspace.

Contact requests

An agent can offer a “contact a human” option in chat. This is backed by a notify skill, commonly named contact_human. When the skill is enabled, the assistant can collect the visitor’s email and message, then deliver the request out of band.

notify is config-only. It does not bind to a connection target, so create it with target.kind set to notify_delivery and target.id set to null.

Configure delivery in the notify skill config:

  • recipientEmails: up to 5 email addresses. Each is emailed a copy of the request. When the list is empty, Radioso falls back to the workspace owner.
  • webhook: an optional { "url": "https://..." }. When set, Radioso also POSTs the request to that URL. Email and webhook both fire when both are configured.

An agent can have more than one notify skill — for example contact_sales and contact_support, each with its own delivery config. A routine step that calls a specific skill by name (#contact_sales) delivers through that skill’s own recipients and webhook. A routine step that reaches the chat-only contact flow without naming a skill, or names a skill that turns out to be disabled or missing, delivers through the contact_human skill when one is configured, then through the agent’s own delivery setting, then through the workspace owner.

Example notify skill config fragment:

json
{
  "delivery": {
    "recipientEmails": ["support@example.com", "ops@example.com"],
    "webhook": { "url": "https://example.com/hooks/contact" }
  },
  "exposedInputs": { "message": true, "email": true }
}

Webhook payload

The webhook receives a POST with a JSON body:

json
{
  "name": "Ada",
  "email": "ada@example.com",
  "message": "Please call me back.",
  "workspaceId": "...",
  "conversationId": "...",
  "requestId": "..."
}

There is no request signature. Treat the webhook URL itself as a secret: keep it private and use a hard-to-guess path so only Radioso knows where to post.

Each request carries an Idempotency-Key header. Delivery is at-least-once, so the same request may arrive more than once on retries. Use the key to de-duplicate.

Radioso sends the request with POST, follows redirects only to publicly routable hosts, and applies a short delivery timeout. Point the webhook at a stable public endpoint.

Read-only skills catalog

The skills catalog is read-only. It helps API, SDK, MCP, and assistant clients understand what work is available and which stable contract owns it.

For example, retrieval.answer points to the retrieval answer API and MCP grounded-answer tool. It does not require callers to switch to a generic POST /skills/{name}/execute contract.

Skill entries include:

  • name and description
  • optional display metadata, such as a UI title or icon hint
  • availability
  • contract references
  • required capabilities
  • diagnostic fields exposed by the implementation
  • skill-owned outcomes, each mapped to a normalized status such as completed or failed

Endpoint reference

Agent, directive, skill, and context-variable bodies are documented field by field in the API Reference.

text
GET    /api/v1/agents
POST   /api/v1/agents
GET    /api/v1/agents/{agentId}
PUT    /api/v1/agents/{agentId}
POST   /api/v1/agents/{agentId}/assistant-logo
DELETE /api/v1/agents/{agentId}/assistant-logo
POST   /api/v1/agents/{agentId}/default
GET    /api/v1/agents/{agentId}/skill-capabilities
GET    /api/v1/agents/{agentId}/directives
POST   /api/v1/agents/{agentId}/directives
POST   /api/v1/agents/{agentId}/directives/draft
PATCH  /api/v1/agents/{agentId}/directives/{directiveId}
DELETE /api/v1/agents/{agentId}/directives/{directiveId}
GET    /api/v1/agents/{agentId}/skills
POST   /api/v1/agents/{agentId}/skills
PATCH  /api/v1/agents/{agentId}/skills/{skillId}
DELETE /api/v1/agents/{agentId}/skills/{skillId}
GET    /api/v1/context-variables
POST   /api/v1/context-variables
GET    /api/v1/context-variables/{id}
PATCH  /api/v1/context-variables/{id}
DELETE /api/v1/context-variables/{id}
GET    /api/v1/agents/{agentId}/context-variables
PUT    /api/v1/agents/{agentId}/context-variables/{variableId}
DELETE /api/v1/agents/{agentId}/context-variables/{variableId}
GET    /api/v1/context-variables/{id}/values
PUT    /api/v1/context-variables/{id}/values
DELETE /api/v1/context-variables/{id}/values
GET    /api/v1/skills
GET    /api/v1/skills/{skillName}

Common failure modes

  • 400 on agent create or update usually means a field failed validation.
  • 401 means the workspace token is missing or invalid.
  • 404 means the agent or skill name does not exist in the current workspace context.
  • A skill can be listed even when the work is executed through another route. Use contractReferences to find the stable execution path.