Agents
Memory & compute
The MemoryStore contract
Agents program against a small, portable memory interface — specified in the silo-spec repository as MemoryStore v0.1 — with four required operations: remember, recall, forget, and recent. Optional operations (ask, overview, rememberTranscript) are feature-detected by presence, so the same agent code runs against the cloud control plane, a self-hosted node, or a local file.
Where the store is backed by the control plane over MCP, the operations map one-to-one onto the tool vocabulary you already know: silo_remember, silo_recall, silo_forget, silo_ask, get_scope.
Write semantics — honest outcomes
A write is not always stored the moment you issue it. Every write returns one of three outcomes, and conforming stores report the true one:
storedDurably written.
queuedAccepted and buffered (for example, the backing node is temporarily unreachable). The store retries; it must never silently degrade to a less private path.
needs_confirmationThe owner has to approve — typically a memory-replacing write. The agent surfaces this state and never confirms on the owner's behalf; confirmation happens in the owner's dashboard.
Two more rules govern writes. Authorization is always server-side: write refusals and confirmation demands come from the backing surface per request, based on the owner's per-silo grant (read-only or read-write) — never from client-side logic. And provenance is append-anchored: memories written by an agent carry who wrote them, over which transport, in a form user-supplied text cannot spoof.
Compute — OpenAI-compatible
Cloud-placed agents generate through the control plane's OpenAI-compatible endpoint. Any OpenAI SDK works — point base_urlat the control plane and authenticate with the agent's credential (OAuth bearer or sc_ key):
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.onesilo.com/v1",
apiKey: process.env.SILO_AGENT_KEY, // sc_... or an OAuth bearer
});
const models = await client.models.list(); // what THIS connection may use
const reply = await client.chat.completions.create({
model: models.data[0].id,
messages: [{ role: "user", content: "Summarize today's tickets." }],
});GET /v1/modelslists the models this connection is allowed to run — pinned model, owner allowlist, and org policy already applied. Model choice is enforced again at execution time.- Usage meters as interactions per model class against the owner's plan; when a budget is exhausted the endpoint answers with a standard OpenAI-style error carrying HTTP 402/429, so off-the-shelf clients fail cleanly. Tokens are recorded for bookkeeping, never as the gate.
- Every call is rate-limited per connection and lands in the audit log.
Or: your own node
Node-placed agents run inference on the owner's hardware. Cloud interactions aren't consumed, and raw conversational content can stay on the device — a self-hosted agent can distill locally and send only distilled statements upward, or use the governed compute endpoint just for distillation while storing nothing raw. The SDK ships both postures as composable store wrappers; which one an agent uses is configuration, not code.