Brainby arc-labs/docs
Sdk typescriptAgents
TypeScript SDK

Agents

Create and manage agents — the named personas that own memories within a namespace. Covers recall.agents.list(), get(), create(), patch(), delete(), and stats().

Agents sit between the organisation and memories in Recall's identity hierarchy: an org has many agents, each agent is bound to a namespace, and all memories written through an agent key are scoped to that agent. Creating and managing agents is an administrative operation, separate from the day-to-day memory pipeline operations exposed on recall.remember() and recall.search().

agents.list(opts?, options?)

GET/v1/agentsAPI key (admin)stable
recall.agents.list(
  opts?: { limit?: number; cursor?: string },
  options?: TransportRequestOptions
): PagedRequest<AgentSummary>

Returns a PagedRequest<AgentSummary>await it for the first page, or for await it to auto-paginate through every agent in the org. This is the same dual-mode iterable pattern used by recall.memory.list() and recall.entity.search(). See Pagination for the full PagedRequest semantics.

Parameters

ParameterTypeRequired
opts.limitnumberoptional
Items per page, clamped server-side to [1, 100].
opts.cursorstringoptional
Explicit cursor override for resuming an interrupted iteration. When omitted, starts from the first page.
optionsTransportRequestOptionsoptional
Per-request transport overrides: signal, maxRetries, timeoutMs. Applied on top of the client defaults.

AgentSummary (per item)

FieldTypePresence
idAgentIdalways
Stable opaque identifier. Never reused after deletion.
namestringalways
Human-readable display name, unique within the org.
namespaceIdstringalways
Namespace the agent is bound to.
createdAtstringalways
ISO 8601 timestamp.
updatedAtstringalways
ISO 8601 timestamp of the last field change.

Examples

// First page only
const page = await recall.agents.list({ limit: 20 })
console.log(page.items, page.hasMore, page.nextCursor)

// Auto-paginate every agent in the org
for await (const agent of recall.agents.list()) {
  console.log(agent.id, agent.name)
}

// Materialize up to 200 agents
const all = await recall.agents.list({ limit: 50 }).toArray({ limit: 200 })

Errors

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or invalid API key.
FORBIDDEN403fatal
Key is valid but does not carry admin scope.

agents.get(id, options?)

GET/v1/agents/:idAPI key (admin)stable
recall.agents.get(id: AgentId, options?: TransportRequestOptions): Promise<AgentDetail>

Returns full detail for a single agent. Throws RecallNotFoundError for unknown or hard-deleted IDs.

Returns

FieldTypePresence
idAgentIdalways
namestringalways
namespaceIdstringalways
createdAtstringalways
updatedAtstringalways
deletedAtstring | nullalways
Set when the agent has been soft-deleted; null for active agents.

Example

import { type AgentId } from '@arc-labs/recall'

const id = 'agt_abc123' as AgentId
const agent = await recall.agents.get(id)
console.log(agent.name, agent.namespaceId, agent.deletedAt)

Errors

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or invalid API key.
FORBIDDEN403fatal
Key lacks admin scope.
NOT_FOUND404fatal
Agent ID does not exist or has been hard-deleted.

agents.create(name, opts?, options?)

POST/v1/agentsAPI key (admin)stable
recall.agents.create(
  name: string,
  opts?: { namespaceId?: string },
  options?: TransportRequestOptions
): Promise<AgentDetail>

Provisions a new agent in the org. The agent name must be unique within the org — the server enforces uniqueness and returns 409 CONFLICT on collision. Once created, the agent can have API keys issued against it via recall.keys.create().

Parameters

ParameterTypeRequired
namestringrequired
Display name for the agent. Must be unique within the org.
opts.namespaceIdstringoptional
Namespace to bind the agent to. Defaults to the namespace bound to the calling API key when omitted.
optionsTransportRequestOptionsoptional
Per-request transport overrides.

Returns

AgentDetail — the same shape as agents.get(). All fields are populated immediately; no async provisioning step.

Example

const agent = await recall.agents.create('billing-assistant', {
  namespaceId: 'ns_prod',
})
console.log('Created agent:', agent.id, agent.name)

// Issue a key for the new agent immediately
const key = await recall.keys.create({
  name: 'billing-assistant-prod',
  agentId: agent.id,
})
// Store key.key in your secret manager — it is returned exactly once.

Errors

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or invalid API key.
FORBIDDEN403fatal
Key lacks admin scope.
CONFLICT409fatal
An agent with this name already exists in the org.
MAX_AGENTS_REACHED429fatal
Org has reached the plan limit for agents. Upgrade the plan or delete unused agents.

agents.patch(id, changes, options?)

PATCH/v1/agents/:idAPI key (admin)stable
recall.agents.patch(
  id: AgentId,
  changes: { name?: string },
  options?: TransportRequestOptions
): Promise<AgentDetail>

Update mutable fields on an existing agent. Currently only name is patchable — the namespaceId binding is immutable after creation. Returns the updated AgentDetail.

Parameters

ParameterTypeRequired
idAgentIdrequired
ID of the agent to update.
changes.namestringoptional
New display name. Must be unique within the org. The server rejects the patch with 409 CONFLICT if the name is taken.
optionsTransportRequestOptionsoptional
Per-request transport overrides.

Example

const updated = await recall.agents.patch('agt_abc123' as AgentId, {
  name: 'billing-assistant-v2',
})
console.log('Renamed to:', updated.name, 'at', updated.updatedAt)

Errors

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or invalid API key.
FORBIDDEN403fatal
Key lacks admin scope.
NOT_FOUND404fatal
Agent ID does not exist.
CONFLICT409fatal
Target name is already taken by another agent.

agents.delete(id, options?)

DELETE/v1/agents/:idAPI key (admin)stable
recall.agents.delete(id: AgentId, options?: TransportRequestOptions): Promise<DeleteResult>

Soft-deletes an agent. The agent's deletedAt is set to the current timestamp, and all API keys bound to that agent stop authenticating immediately. The agent's memories are not deleted.

Returns { id, deletedAt, soft: true }.

Deleting an agent does not cascade to its memories. They remain queryable by scope until you explicitly call recall.forget() targeting the agent's scope. If you want a clean teardown, forget the memories first, then delete the agent.

Returns

FieldTypePresence
idAgentIdalways
The deleted agent's ID.
deletedAtstringalways
ISO 8601 timestamp of the deletion.
softtruealways
Always true — hard deletion is not available via the SDK.

Example

// Step 1: forget all memories belonging to the agent
await recall.forget({ filter: { agentId: 'agt_abc123' }, reason: 'decommissioning agent' })

// Step 2: delete the agent itself
const result = await recall.agents.delete('agt_abc123' as AgentId)
console.log('Deleted at:', result.deletedAt)

Errors

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or invalid API key.
FORBIDDEN403fatal
Key lacks admin scope.
NOT_FOUND404fatal
Agent ID does not exist or was already deleted.

agents.stats(id, options?)

GET/v1/agents/:id/statsAPI key (admin)stable
recall.agents.stats(id: AgentId, options?: TransportRequestOptions): Promise<AgentStats>

Returns usage statistics for a single agent. Useful for dashboards, capacity planning, and billing attribution.

Returns

FieldTypePresence
memoryCountnumberalways
Total active (non-deleted) memories owned by this agent.
sessionCountnumberalways
Number of distinct sessions the agent has participated in.
lastActiveAtstring
ISO 8601 timestamp of the most recent memory write or read. Absent when the agent has never been used.

Example

const stats = await recall.agents.stats('agt_abc123' as AgentId)
console.log(`${stats.memoryCount} memories, last active: ${stats.lastActiveAt ?? 'never'}`)

// Gate on activity before deciding to decommission
if (!stats.lastActiveAt) {
  await recall.agents.delete('agt_abc123' as AgentId)
}

Errors

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or invalid API key.
FORBIDDEN403fatal
Key lacks admin scope.
NOT_FOUND404fatal
Agent ID does not exist.

Was this page helpful?

On this page