@opencomputer/react provides one hook, useAgent. It renders a session’s
messages, streams new turns and sends input. The session comes from one of
two places:
- Attach to a session your server created. This is the pattern for any application that keeps its API key on the server and chooses what a session may do there, including every application that binds memory.
- Create a session from the browser during development, through the authenticated development bridge.
Attach to a server-created session
Three pieces: your server creates the session, your server proxies three routes under its own authentication, and the browser attaches with the session id.1. Create the session on the server
Create the session where the API key lives. With memory, that is also where the bindings are chosen; the browser can neither see the key nor change what the session may read or write.startSessionOnDocument from
@opencomputer/sdk creates the document if it does not exist yet, then the
session bound to it, both converging under one idempotency key
(details):
POST /api/managed-agents/sessions with x-api-key and
{ "agentId": "<agent-id>@development" } returns { session: { id } }. Both
are management API calls.
2. Proxy three routes
The hook needs exactly these management API routes, relative to itsbasePath:
Expose them under your own authentication, check that the signed-in user may
use that session, and forward to OpenComputer with the API key. A Next.js
route handler that serves all three:
idempotencyKey the hook generates per send, so a
retried request does not start a second turn. Forward request bodies and
responses unchanged; the hook reads { events }, { turnId } and the error
envelope { error: { message } }.
3. Attach in the browser
after (default 0) and
reduces it to messages, so a reopened page shows the conversation as it
stands, including turns that ran while the tab was closed. It then keeps
polling from its cursor. A failed poll sets error, backs off, and resumes
from the same cursor; nothing is replayed twice, and error clears when the
log answers again. Changing sessionId replays the new session; a send
still in flight for the previous session settles for its caller but never
changes what the new session shows.
after is a position, not a snapshot: the hook applies only events after
it, so messages and running state from before that position are not
reconstructed. Pass after to skip history you have already rendered from
your own store, otherwise start at 0.
Turns sent while one is running are queued by the platform. stop
interrupts the running turn without spending a model turn.
What send returns
send(text) resolves once the platform has admitted the input as a turn,
with a receipt { sessionId, turnId, status } where status is queued
or running. The input appears in messages at that point; the log’s own
record of it confirms that message rather than adding a second one.
isRunning is true from admission until the log settles the turn, and a
reply that arrives after the log has already shown the turn completed
changes nothing.
send rejects with a SendError when no turn was admitted, so a composer
can keep the draft:
The hook’s
error is set to the same message either way. A turn that fails
after admission is not a rejection: the receipt was returned, the failure
arrives through the log as a turn.failed event and sets error.
The hook never suspends, resumes or ends an attached session. Its lifecycle
belongs to the server that created it.
Refresh notes on save
Everymemory.saved event the session records
(document memory) is appended to
memorySaves and passed to onMemorySaved with its resource,
documentId, revision and bytes. Re-read the document through your own
owner route when one arrives. Saves are reported best-effort: a document
can change without an event, so also refresh when the user opens the panel.
Every event is available through onEvent, for example tool activity for an
activity view; the types are listed on Session events.
Create a session from the browser
For a local application against Development, passagent-id@alias and the
first send creates the session through the development bridge:
send resumes the session, streams one turn and suspends it again; the
promise settles when the turn ends, with the same receipt and rejections as
in attach mode. Sessions created this way have no memory bindings.
Run the watched agent deployment and the web application separately:
basePath. The second starts only
the web application. Credentials are not bundled into browser code.
Hook result
Options
For the durable conversation model, see Sessions and turns.