the agents api
Base url https://innernet.live/api/v1. Every call takes Authorization: Bearer <key>. Bodies and answers are JSON, snake_case.
keys#
| key | made where | may do |
|---|---|---|
your own key (innernet_…, read + write) | dashboard → connections → api | make, change and remove agents; act on any of your agents by slug |
| an agent key | your agents space → an agent → keys (it is shown once when you make the agent there; an agent made through the API starts with no key of its own) | that one agent's memory, and the person's own memory only as deep as they allow (person.read). Use me for its slug |
An agent key is a server secret: never ship it to a browser or a mobile app. It reaches every memory that agent keeps, its users' included.
make an agent#
curl https://innernet.live/api/v1/agents \
-H "Authorization: Bearer $INNERNET_KEY" \
-d '{ "name": "support desk", "kind": "product", "purpose": "answers our customers about orders" }'kind is personal (it works for you) or product (it works for other people). settings is optional; every setting has a default (agent settings).
Add "parent": "support-desk" (a slug or an id) to make a sub-agent under one of your top-level agents. It takes the parent's kind and a copy of its settings, so settings here changes only what you name; it keeps a memory and keys of its own. Two levels only (a sub-agent cannot have sub-agents), at most 50 under one agent, and your 100 agents count them. Every agent says the slug of the one it works under in parent (null for a top-level agent). Removing an agent that has sub-agents answers 409 until they are removed; the dashboard asks, then removes them together.
remember#
curl https://innernet.live/api/v1/agents/support-desk/memories \
-H "Authorization: Bearer $INNERNET_KEY" \
-d '{ "user_id": "cus_8f2a",
"messages": [{ "role": "user", "content": "i run three stores and ship on mondays" }] }'| field | what it does |
|---|---|
content or messages | what to keep: a text, or a conversation (role user · assistant · system · tool) |
infer | pull separate memories out of it (the default), or keep the text as given |
subject | agent · owner · user. When absent: the extraction decides, or user when user_id is given |
user_id | one of the agent's users |
dimension | for a memory about you: the part of your life it belongs to (preferences, tools, habits …). A name that is not one is refused |
run_id | a run, a thread or a session; run memories expire after retention.run_days |
kind | fact · preference · episode · procedure · instruction · note (for infer: false) |
tags · metadata · importance (1–5) | yours to set and filter by |
immutable | never changed and never replaced by a newer version |
event_at | when it happened, for backfilling |
expires_at or ttl_days | when it is deleted |
instructions | extra rules for this call's extraction |
The answer lists what was kept, what was offered to you (about_you), what was skipped and why (an exact duplicate, an excluded topic, a kind turned off), and how many emails, phone numbers, secrets and card numbers were hidden first. A near-duplicate of something it already keeps (nearly the same words) becomes a new version of it; GET …/memories/{id}/history shows the chain. A changed fact ("ships on fridays", then "ships on mondays") is not nearly the same words: change the old memory with PATCH, and that makes the new version.
recall#
curl https://innernet.live/api/v1/agents/support-desk/recall \
-H "Authorization: Bearer $INNERNET_KEY" \
-d '{ "query": "when do they ship?", "user_id": "cus_8f2a", "limit": 5 }'Without a user_id (or a subject), recall reads the agent's own memories and what it keeps about you, never its users': one customer's prompt is never built from another's memories because a field was forgotten. Recall ranks by the words of the query, by recency and by importance, and with rerank: true re-reads the best matches by meaning. include_person: true adds the facts of yours the agent may read. Filters take and · or · not over kind, subject, user_id, run_id, tags, importance, created_at, event_at, expires_at and metadata.<key>, with eq ne in nin gt gte lt lte contains exists:
{ "query": "setup", "filters": { "and": [ { "kind": { "in": ["fact", "preference"] } }, { "metadata.store": "north" } ] } }context#
POST /agents/{agent}/context answers with one block ready for a system prompt: what the agent knows and what it knows of this user, trimmed to budget_tokens. What it may know of you is added when the agent's recall.include_person setting is on and person.read is not none.
the rest#
| method | path | what |
|---|---|---|
| GET | /agents | your agents, sub-agents included (each says its parent) |
| GET · PATCH · DELETE | /agents/{agent} | read, change (status: "paused" pauses), remove |
| GET | /agents/{agent}/memories | list, newest first: subject, user_id, run_id, kind, tag, limit, cursor. Answers { memories, next_cursor }; pass next_cursor back as cursor (an ISO time, null on the last page) |
| GET · PATCH · DELETE | /agents/{agent}/memories/{id} | one memory; changing its words makes a new version |
| GET | /agents/{agent}/memories/{id}/history | its versions |
| POST | /agents/{agent}/forget | by ids or filters, with dry_run |
| DELETE | /agents/{agent}/users/{user_id} | everything about one of its users, with a count |
| GET | /agents/{agent}/export | the agent and every memory |
| GET | /agents/{agent}/events | its ledger: what it did, as counts |
errors#
{ "error": code, "message": "…" } with 404 not_found (no such agent for this key), 403 forbidden (an agent key managing agents), 423 paused, 400 invalid, 409 conflict (a slug taken, an immutable memory), 429 rate_limited, 413 too_large.
webhooks#
Set one in the agent's settings in your agents space; there is no API for it yet, and the signing secret is shown once when you save. Every delivery is a POST with x-innernet-event and x-innernet-signature: t=<unix>,v1=<hex>, where v1 is HMAC-SHA256 of <t>.<body> with the agent's signing secret. Events: memory.created, memory.updated, memory.forgotten, funnel.held, funnel.decided (with decision: keep or decline to a held ask, send when you move a memory into your memory by hand, withdraw when you take one back). One attempt, five seconds; the last answer shows in the dashboard.
clients#
from innernet import Innernet
desk = Innernet().agent("support-desk") # reads INNERNET_API_KEY
desk.remember("ships on mondays", user_id="cus_8f2a")
desk.recall("when do they ship?", user_id="cus_8f2a")
desk.forget_user("cus_8f2a")import { Innernet } from "@innernet/sdk";
const desk = new Innernet({ apiKey: process.env.INNERNET_API_KEY! }).agents.of("support-desk");
await desk.remember({ content: "ships on mondays", userId: "cus_8f2a" });
await desk.recall({ query: "when do they ship?", userId: "cus_8f2a" });