Brainby arc-labs/docs
Sdk typescriptEntities
TypeScript SDK

Entities

Reference for the recall.entity resource — get, search, and the current state of graph traversal.

Entities are the typed-graph half of Recall's data model: people, projects, places, products — anything an extraction can identify and link memories to. The write pipeline creates entities as a side effect of running on conversation turns; this resource lets your application read them back.

recall.entity.get(id)

GET/v1/entities/:idAPI keystable
recall.entity.get(id: EntityId, options?: TransportRequestOptions): Promise<EntityDetail>;

Returns full detail for a single entity. Throws RecallNotFoundError for unknown IDs.

Returns

FieldTypePresence
idEntityIdalways
namestringalways
Canonical display name.
kindstringalways
Entity kind (e.g. 'person', 'project', 'place'). Open-set string — not a closed enum.
aliasesstring[]always
Known aliases, deduplicated. The extraction stage merges aliases as evidence accumulates.
scopeScopealways
The bound (userId, agentId, sessionId?, namespace).
createdAtstringalways
ISO 8601.
updatedAtstringalways
ISO 8601.
deletedAtstring | nullalways
Set when the entity has been soft-deleted; null otherwise.

Example

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

const id = 'ent_abc123' as EntityId;
const entity = await recall.entity.get(id);
console.log(entity.name, entity.kind, entity.aliases);

recall.entity.search(query?, opts?)

GET/v1/entitiesAPI keystable
recall.entity.search(
  query?: string,
  opts?: EntitySearchOptions,
  options?: TransportRequestOptions,
): PagedRequest<EntitySummary>;

Search entities by name (case-insensitive prefix match), or list every entity in scope when query is omitted. Returns a PagedRequest<EntitySummary>await it for the first page, for await it to auto-paginate.

Inputs

ParameterTypeRequired
querystringoptional
Optional name prefix. Empty / undefined returns all entities.
opts.limitnumberoptional
Page size (default 20, clamped server-side to [1, 100]).
opts.cursorstringoptional
Explicit cursor override for resuming an interrupted iteration.

EntitySummary (per item)

FieldTypePresence
idEntityIdalways
namestringalways
kindstringalways
aliasesstring[]always

Examples

// First page only
const page = await recall.entity.search('Arc');
console.log(page.items, page.hasMore, page.nextCursor);

// Auto-paginate every entity in scope
for await (const e of recall.entity.search()) {
  console.log(e.name, e.kind);
}

// Materialize with a cap
const top100 = await recall.entity.search('p', { limit: 50 }).toArray({ limit: 100 });

See Pagination for the full PagedRequest semantics.

What's NOT (yet) in the resource

The current SDK exposes get and search. The following operations exist on the REST API but do not yet have first-class SDK helpers:

  • GET /v1/entities/:id/graph — walk the entity-relation graph from a starting node.
  • POST /v1/entities/:id/merge — merge two entities (fold one into the other and rewrite incoming edges).
  • GET /v1/relations / GET /v1/relations/:id — list and inspect relation rows.

For these, drop into the transport directly. The Recall class does not expose the transport publicly, so the canonical workaround is to construct your own:

import { HttpTransport } from '@arc-labs/recall';

const transport = new HttpTransport({
  baseUrl: process.env.RECALL_URL!,
  apiKey: process.env.RECALL_API_KEY!,
});

const graph = await transport.request<unknown>('GET', `/v1/entities/${id}/graph`);

The transport request<T> helper handles auth, retries, idempotency keys, the API-version header, and error translation — you get the same typed errors as the resource methods. See Transport for the full interface.

First-class recall.entity.getGraph(id) and recall.entity.merge(srcId, dstId) helpers are tracked for a future minor release. The shape of the response is stable; only the SDK wrapper is missing.

Errors

Both methods translate server errors via the standard hierarchy:

CodeStatusRetry
UNAUTHORIZED401fatal
Missing or expired API key.
FORBIDDEN403fatal
Key valid but lacks read permission for this namespace.
NOT_FOUND404fatal
Entity ID does not exist (or has been hard-deleted).
UNKNOWN429retriable
Rate limit. Retry after retryAfterMs.

When to use search vs the read pipeline

recall.entity.search() is prefix search by name. It does not run the read pipeline, does not score by relevance, and does not consider the entity-graph at retrieval time. Use it for typeahead, "browse all my entities", and admin tooling.

When you want "which entities are most relevant to this query?", call recall.search() instead — its entity_graph retriever will surface entities through the memories that link to them, scored against the query. The two endpoints serve different purposes.

When to use get vs explain

recall.entity.get(id) returns just the entity. It does not return the memories that mention it.

To find memories about an entity, call recall.search() with the entity name in the query — the pipeline will surface them. There is no current "memories that reference entity X" SDK helper, though the underlying join is exposed in the entity-graph endpoint linked above.

Common pitfalls

The kind field is not a closed enum. The extraction stage uses an open-set kind taxonomy — adding a new entity kind on the server does not require an SDK change. Pattern-match cautiously.

aliases are merged eagerly. If two extractions for the same name produce subtly different surface forms ("GitHub" and "github.com"), the dedupe stage may merge them under one canonical name with both aliases. Treat aliases as a fuzzy match list, not authoritative variants.

Soft-deleted entities (deletedAt !== null) are filtered out of search() results by default. To list them you would need ?includeDeleted=true on the underlying endpoint — currently only available via transport.request with manual query parameters.

Was this page helpful?

On this page