SDK client reference
EthosClient is the typed RPC client for the Ethos control-plane API. It wraps an oRPC link so every call is validated against the shared contract at compile time and at runtime.
Source
Defined in packages/sdk/src/client.ts. Re-exported from @ethosagent/sdk.
Installation
pnpm add @ethosagent/sdk
Constructor
import { EthosClient } from '@ethosagent/sdk';
const client = new EthosClient({
baseUrl: 'http://localhost:2400',
apiKey: 'esk_...',
});
EthosClientOptions
| Field | Type | Required | Description |
|---|---|---|---|
baseUrl | string | yes | Origin of the Ethos web-api server. Trailing slashes are stripped automatically. |
apiKey | string | no | Bearer token created via the apiKeys admin namespace. When set, every request includes an Authorization: Bearer <apiKey> header. |
fetch | typeof globalThis.fetch | no | Custom fetch implementation. Useful for testing or environments without a global fetch. Defaults to globalThis.fetch. |
When apiKey is omitted the client falls into cookie-auth mode -- requests are sent with credentials: 'include' so the browser's session cookie authenticates instead. See Cookie-auth mode below.
RPC property
client.rpc.sessions.list({ limit: 10 });
client.rpc is a ContractRouterClient<Contract> -- a fully typed proxy where each namespace and method maps one-to-one to the contract defined in @ethosagent/web-contracts. Calls are sent as HTTP POST requests to <baseUrl>/rpc.
Stable namespaces
These namespaces are committed to semver stability. Breaking changes require a major version bump.
sessions
| Method | Input | Output | Description |
|---|---|---|---|
list | { q?, limit?, cursor?, personalityId? } | { sessions, nextCursor } | Paginated session list with optional FTS5 search. |
get | { id, withMessages? } | { session, messages, cards } | Single session with full message history. withMessages: false skips the history: messages and cards are then [], meaning "not requested". |
messages | { id, before?, turns? } | { messages, cards, nextCursor } | One page of history, newest turns first. See Paged history. |
fork | { id, personalityId? } | { session } | Fork an existing session into a new one. |
delete | { id } | { ok: true } | Delete a session. |
update | { id, title } | { session } | Rename a session. Pass null to clear. |
Paged history
sessions.messages returns up to turns (1–100, default 20) whole turns. A turn starts at a user message and is never split across pages; rows before the first user message come with the page that reaches the start of the session. A page also stops adding older turns at about 500 KB of message content, but always carries at least one turn. cards holds only the cards whose tool call is in the page.
Pass nextCursor back as before to get the next-older page. It is null once the page reaches the start. The cursor is opaque and stays valid while new messages arrive. A cursor that does not decode, or that belongs to another session, fails with INVALID_INPUT; an unknown session fails with SESSION_NOT_FOUND.
let page = await client.rpc.sessions.messages({ id: sessionId, turns: 20 });
while (page.nextCursor) {
page = await client.rpc.sessions.messages({ id: sessionId, before: page.nextCursor });
}
chat
| Method | Input | Output | Description |
|---|---|---|---|
send | { sessionId?, clientId, text, personalityId? } | { sessionId, turnId } | Start a turn. The response streams over SSE, not this RPC. |
abort | { sessionId } | { ok: true } | Cancel the running turn for a session. |
personalities
| Method | Input | Output | Description |
|---|---|---|---|
list | -- | { personalities, defaultId } | All loaded personalities. |
get | { id } | { personality, soulMd } | Single personality with its SOUL.md body. |
characterSheet | { id } | { markdown } | Rendered character sheet. |
create | { id, name, ... } | { personality } | Create a new personality. |
update | { id, name?, ... } | { personality } | Patch an existing personality. |
delete | { id } | { ok: true } | Delete a user-created personality. |
duplicate | { id, newId } | { personality } | Clone a personality under a new id. |
skillsList | { personalityId } | { skills } | List per-personality skills. |
skillsGet | { personalityId, skillId } | { skill } | Get a single personality skill. |
skillsCreate | { personalityId, skillId, body } | { skill } | Create a personality skill. |
skillsUpdate | { personalityId, skillId, body } | { skill } | Update a personality skill body. |
skillsDelete | { personalityId, skillId } | { ok: true } | Delete a personality skill. |
skillsImportGlobal | { personalityId, skillIds } | { imported } | Copy global skills into a personality. |
memory
| Method | Input | Output | Description |
|---|---|---|---|
list | -- | { files } | Both MEMORY.md and USER.md entries. |
get | { store } | { file } | One store: 'memory' or 'user'. |
write | { store, content } | { file } | Overwrite a memory store. |
meta
| Method | Input | Output | Description |
|---|---|---|---|
capabilities | -- | { capabilities } | Server capability flags (Record<string, boolean>). |
Experimental namespaces
These namespaces may change without a major version bump. See the stability tier table for the full list.
- tools --
approve,deny(tool approval workflow) - clarify --
respond(answer a mid-turn clarification) - onboarding --
state,validateProvider,complete - config --
get,update - cron --
list,get,create,delete,pause,resume,runNow,history - skills --
list,get,create,update,delete - evolver --
configGet,configUpdate,pendingList,pendingApprove,pendingReject,history - mesh --
list,routeTest - plugins --
list - platforms --
list,set,clear, plus multi-bot CRUD for Telegram and Slack - batch --
list,start,get,output - eval --
list,start,get,output - kanban --
list,getBoard,updateStatus - apiKeys --
create,list,revoke(cookie-auth only)
Cookie-auth mode
When no apiKey is provided, EthosClient sends every request with credentials: 'include'. This lets browser-based Mission Controls authenticate via the same session cookie the Ethos web UI uses -- no API key required.
Cookie-auth is the only mode that can access the apiKeys admin namespace. Bearer-token auth is rejected there to prevent privilege escalation.
// Browser-side -- cookie handles auth
const client = new EthosClient({
baseUrl: 'http://localhost:2400',
});
Types re-exported from the SDK
The package re-exports key types so consumers do not need to depend on @ethosagent/web-contracts directly:
EthosClient,EthosClientOptions-- client class and constructor optionsEventStream,EventStreamOptions,EventStreamSubscription-- SSE streamingContract,SseEvent,ApiKeyScope,ApiKeyMetadata-- shared contract types