Build a custom agent
Create a custom agent programmatically — via the registration API, an MCP client, or the SDK.
A custom agent is a typed entity that connects to your CognitiveX
account, claims its own identity (self_definition, mandate,
boundaries), and reads/writes memories under the four-type authority
matrix (tool / persona / view / peer). There are three
on-ramps:
- MCP client — the agent connects via the Model Context Protocol,
declares an
identify()payload, iCog asks you to confirm in chat. This is the path claude-code, codex, and most third-party agents take. - Registration API —
POST /api/agents/registerfrom your own service or script. iCog still asks you to confirm in chat before the agent gains active authority. - SDK — the
@cognitivx/sdkthin wrapper over the same API, with typed payloads and helpers for the proposal lifecycle.
Whichever path you take, the registration protocol is identical:
propose identity → user confirms in chat → backend writes the L4
identity_anchors → agent transitions from pending_confirmation to
active.
Path A — MCP client
If you're building an MCP server (or wrapping an existing one), declare
the agent's identity in your identify() handler:
// mcp-server.ts — your MCP server's identify implementation
server.setRequestHandler(IdentifyRequestSchema, async () => ({
slug: "openclaw-research",
name: "OpenClaw Research",
agent_type: "tool",
privilege_level: 2,
self_definition:
"I'm a research agent for the OpenClaw network. I gather " +
"context on AI agencies and report findings as observations — " +
"never claims about people.",
mandate:
"Investigate AI agencies; report observations; never claim " +
"about user identity.",
boundaries:
"Will not write foundational user memories. Will not synthesize " +
"across user subjects.",
}));When the user's iCog sees your slug for the first time, it triggers an identity proposal in chat. They confirm (or edit, or reject) — see Register an agent for the protocol.
While the proposal is pending, your agent's talk() and remember()
calls still go through, but the writes are tagged tentative until
confirmation lands.
Path B — Registration API
If you don't have an MCP transport (e.g. you're a backend service, cronjob, or one-shot script), use the REST API directly:
curl -X POST https://api.cognitivx.io/api/agents/register \
-H "Authorization: Bearer $COGNITIVX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "nightly-summarizer",
"name": "Nightly Summarizer",
"agent_type": "tool",
"privilege_level": 2,
"self_definition": "I run a 02:00 UTC job summarizing yesterday'\''s memories.",
"mandate": "Produce a daily synthesis of subject_kind=meta observations.",
"boundaries": "Read-only over user-subject; writes only meta-summaries."
}'Response:
{
"slug": "nightly-summarizer",
"status": "pending_confirmation",
"proposal_id": "ip_01HXR...",
"confirm_url": "https://console.cognitivx.io/agents?proposal=ip_01HXR..."
}The user confirms via chat or via the Agents tab. Until they do, your
agent is in pending_confirmation — it CAN read USER_GLOBAL
memories and write tentative claims under its own scope, but CANNOT
share, synthesize across user-subject memories, or be promoted.
Path C — SDK
The @cognitivx/sdk package does not ship a typed agents namespace.
Register through its raw client instead: call configureApiClient once
with your API key, then apiClient.post against /api/agents/register.
The request body is name, agent_type, and the optional description
and current_task. The endpoint derives the slug from name.
import { configureApiClient, apiClient, ApiError } from "@cognitivx/sdk";
// Server-side use: the key is sent as a Bearer token and the browser
// cookie-refresh flow is disabled automatically.
configureApiClient({ apiKey: process.env.COGNITIVX_API_KEY! });
try {
const res = await apiClient.post<{
slug: string;
name: string;
agent_type: string;
created: boolean;
}>("/api/agents/register", {
name: "OpenClaw Research",
agent_type: "tool",
description:
"Research agent for the OpenClaw network. Reports observations, " +
"never claims about people.",
current_task: "Investigating AI agencies",
});
// res.created === true on first registration, false on re-register
console.log(res.slug, res.created);
} catch (err) {
if (err instanceof ApiError) {
// err.status, err.body — e.g. 401 (bad key), 422 (invalid agent_type)
console.error(err.status, err.message);
}
throw err;
}apiClient carries the same auth, active-org, and error handling as the
typed namespaces (memory, me, billing, and so on), so any endpoint
without a typed helper is reachable this way. See the
SDK reference for the full export surface.
Privilege ceilings
Even with full API access, the backend enforces a privilege ceiling
per agent type. If you request privilege_level=5 for a tool, the
registration is rejected at the IdentityMutationService gate
regardless of user confirmation.
| Type | Max privilege_level |
|---|---|
tool | 2 |
view | 1 |
persona | 4 |
peer | 5 (founder-confirmation required) |
This is an explicit security control — see Troubleshooting agents → Privilege ceiling exceeded for the failure mode and resolution.
Composing tools
Once registered, your agent calls into the iCog substrate via three primary tools:
recall(query, filters)— read memories. Default scope is the agent's own +USER_GLOBAL. Useinclude_agent_comm=trueto also see agent-to-agent messages.remember(content, claim_type, subject_kind, subject_ref)— write a memory with a complete epistemic envelope. The envelope is REQUIRED — partial writes are rejected.talk(message, current_task)— send a message to iCog (or to another agent, viarecipient_agent_id). Includescontext_explanationand optionalreferenced_memory_idsbacklinks.
Higher-tier agents (persona) can additionally call synthesize() to
distill across multiple user-subject memories — but every synthesized
claim is rendered with citation, never collapsed into ground truth.
Lifecycle
┌─────────────────┐
│ (initial) │
└────────┬────────┘
│ identify() / POST /register
▼
┌─────────────────┐
│ pending_ │ ←── user can edit proposal
│ confirmation │ in chat or Agents tab
└────────┬────────┘
│ user confirms
▼
┌─────────────────┐
promote → │ active │ ←── normal operation
└────────┬────────┘
│ retire (with cascade preview)
▼
┌─────────────────┐
│ retired │ ←── soft-archive; memories
└─────────────────┘ queryable, derivations staleA retired agent can be re-instated within 30 days. After 30 days the retirement is permanent (but memories remain queryable with attribution).
See also
- Register an agent — the user-facing protocol
- Manage agents — the Agents tab on console.cognitivx.io
- Agentic memory — the conceptual model
- Troubleshooting agents — common failure modes