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-session header, 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 is GET /v1/agents/{slug}/detail, which this SDK does not expose. Every call to agents.get() 404s, regardless of whether the slug is valid. If you need agent detail, call GET /v1/agents/{slug}/detail directly.

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's POST /v1/agents/{slug}/invoke — but the runtime has no such route (its only /invoke path is /v1/tools/{name}/invoke), so the proxied call 404s. There is also no user-facing WebSocket or SSE anywhere in Catentio; the websocket_url field 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 }. Real run_ids are 26-character lowercase base32 with no prefix (e.g. gk3n7q2fzja4bdm6xr8v1cwt5p), never run_.... 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).

Next

  • Runs — the real run surface (list, cancel; no per-run get).
  • Tools — the capability registry that constrains what an agent can do.
  • Skills — versioned playbooks an agent loads on demand.