Agents
An agent is a named Claude principal the runtime resolves by slug — its own model, system prompt, allowed-tools list, and defaults. This namespace lists the roster and fetches one for detail. It does not give you a working way to start a run — see agents.invoke below.
For the wire-level reference, see API → Agents.
Auth. The routes behind this namespace require the control plane's
x-catentio-sessionheader, which this SDK never sends. Neither API-key mode nor Bearer-session mode authenticates against/v1/agents/*. See SDKs → Auth: what actually works.
Namespace
catentio.agents — three methods:
catentio.agents.list()
catentio.agents.get(slug)
catentio.agents.invoke(slug, input)
Agent create/update/delete/avatar management exist on the control plane (POST /v1/agents, PATCH /v1/agents/{slug}, PATCH /v1/agents/{slug}/model, PATCH /v1/agents/{slug}/voice, DELETE /v1/agents/{slug}, and the avatar GET/PUT/DELETE trio) but this SDK doesn't wrap any of them — call the REST API directly for those.
Methods
agents.list
Signature. catentio.agents.list(token?): Promise<{ data: Agent[]; meta: { total: number; builtin: number; custom: number } }>
Returns the agent roster. Backs the portal's Dashboard → Agents page.
import { CatentioSaasClient } from '@forjio/catentio-saas-node';
const catentio = new CatentioSaasClient({ session });
const { data: agents } = await catentio.agents.list();
for (const a of agents) {
console.log(a.slug, a.model, a.is_builtin);
}
agents.get — targets a route that does not exist
Signature. catentio.agents.get(slug, token?): Promise<Agent>
This call fails. It sends
GET /v1/agents/{slug}. That route does not exist on the control plane — the real detail route isGET /v1/agents/{slug}/detail, which this SDK does not expose. Every call toagents.get()404s, regardless of whether the slug is valid. If you need agent detail, callGET /v1/agents/{slug}/detaildirectly.
agents.invoke — targets a route that is broken end-to-end
Signature. catentio.agents.invoke(slug, input, token?): Promise<{ run_id: string; status: string; websocket_url: string }>
This call fails. It sends
POST /v1/agents/{slug}/invoke. The control-plane route exists and proxies to the runtime'sPOST /v1/agents/{slug}/invoke— but the runtime has no such route (its only/invokepath is/v1/tools/{name}/invoke), so the proxied call 404s. There is also no user-facing WebSocket or SSE anywhere in Catentio; thewebsocket_urlfield in the response type is a passthrough of whatever the (nonexistent) runtime route would have returned — it is not something you can connect to.The real way to start a run is
POST /v1/runs, which this SDK has no method for. Body:{ agent, transport: "rest", prompt (or message, exactly one required), thread_id?, channel_id?, override? }→201 { run_id, status }. Realrun_ids are 26-character lowercase base32 with no prefix (e.g.gk3n7q2fzja4bdm6xr8v1cwt5p), neverrun_.... Call it with the low-level client:const { run_id, status } = await catentio.api.post('/v1/runs', { agent: 'hachimi', transport: 'rest', prompt: "What's the status of pawpado's deploy?", });
For reference, the CP's InvokeRequest body (the one agents.invoke actually sends, even though the call fails) is { prompt (required, min length 1), work_mode?: "single_session" | "taskrunner", conversation_context? }. There is no message field and no attachments field, despite what the input type below implies.
Types
interface Agent {
slug: string;
description: string;
model: string;
module: string;
class_name: string;
prompt_length: number;
allowed_tools_count: number;
allowed_tools: string[];
is_builtin: boolean;
default_model: string | null;
selection_mode: string | null;
reasoning: string | null;
resolver_enforce: boolean;
memory_mode: string | null;
// custom (non-built-in) agents only:
owner_customer_id?: string;
version?: number;
}
There is no name, display_name, tagline, persona, tool_budget, voice_id (not on this row), avatar_url, skills, tools_count, created_at, or updated_at field on the real object — don't rely on them.
When the control plane runs with CATENTIO_PORTAL_VISIBILITY=public and the agent is built-in, it blanks prompt, session_prompt, heartbeat_prompt, module, class_name, allowlist_block, allowlist_add and sets redacted: true. It does not strip tool definitions.
The model is not immutable after creation — PATCH /v1/agents/{slug}/model exists on the control plane (just not wrapped by this SDK).
Errors
The real error shape is FastAPI's {"detail": ...}, not a {code, status} pair.
| Status | When |
|---|---|
| 401 | Missing/invalid session — every route in this namespace requires x-catentio-session, which this SDK never sends. |
| 404 | Always, for agents.get(); and via the runtime proxy, for agents.invoke(). See the warnings above. |
| 422 | Validation error on the underlying schema (FastAPI). |