@robota-sdk/agent-transport/http
HTTP transport for the Robota SDK, built on Hono. It exposes a running agent session as a small set of HTTP routes, so a browser, another service, or any HTTP client can submit prompts, stream the agent's response as Server-Sent Events, and read the session's state. The result is a Hono app rather than a listening server: you mount it in your own Hono application or serve it yourself.
Installation
npm install @robota-sdk/agent-transport honoThis subpath reaches no Node built-in or Node global, so it runs wherever Hono does; on Node it needs
22.12 or later. hono is an optional peer dependency of the package, installed for this subpath only;
your application serves or mounts the routes with it.
Usage
createHttpTransport wraps the routes as a transport with the standard attach / start / stop
lifecycle. After start(), getApp() returns the Hono app to serve.
import { createHttpTransport } from '@robota-sdk/agent-transport/http';
import type { IHttpTransportSession } from '@robota-sdk/agent-transport/http';
declare const session: IHttpTransportSession; // e.g. an InteractiveSession from @robota-sdk/agent-framework
const transport = createHttpTransport({ basePath: '/agent' });
transport.attach(session);
await transport.start();
const app = transport.getApp(); // a Hono app; serve it, or mount it in your own app
const token = transport.getAdmissionToken(); // hand this to your clientEvery request must carry Authorization: Bearer <token>; anything else is answered 401 before it
reaches a route. When you omit admission, a random per-launch token is minted and
getAdmissionToken() returns it. Pass admission: { token } to use a token you chose, or
admission: { open: true, openReason: '…' } to run without a credential when something in front of
the routes (a gateway, your own auth middleware) already decides who may reach them. openReason is
required, and a token together with open: true is rejected.
Mounting the routes in your own app
createAgentRoutes returns the same routes as a Hono router. It resolves the session per request
through sessionFactory, which receives the Hono request context, so one app can serve several
sessions (for example, looked up from a request header). Here admission is required. A token minted
inside createAgentRoutes could never be read back, so pass one you know: your own, or the result of
resolveAdmission() from @robota-sdk/agent-transport.
import { createAgentRoutes } from '@robota-sdk/agent-transport/http';
import type { IHttpTransportSession } from '@robota-sdk/agent-transport/http';
import { Hono } from 'hono';
declare const session: IHttpTransportSession;
declare const agentToken: string; // shared with your clients out of band
const app = new Hono();
app.route(
'/agent',
createAgentRoutes({
sessionFactory: () => session, // may also look the session up from the request context
admission: { token: agentToken },
}),
);sessionFactory may return a new wrapper object on each call. /submit keys its one-turn-at-a-time
check on getSession().getSessionId(), not on object identity.
Routes
| Method | Path | Purpose |
|---|---|---|
| POST | /submit | Body { "prompt": string, "receivePrompts"?: boolean }. Runs a turn and streams text_delta, tool_start, tool_end, thinking, then complete, interrupted or error as SSE. With receivePrompts: true the stream also carries permission_request, ask_request and prompt_resolved. 409 while a turn is already running. |
| POST | /command | Body { "name": string, "args"?: string }. Runs a session command on behalf of a remote caller. |
| POST | /abort | Aborts the running turn. |
| POST | /cancel-queue | Drops the queued prompt. |
| GET | /messages | The conversation history. |
| GET | /context | The context-window state. |
| GET | /executing | { "executing": boolean }, using the same rule /submit uses to answer 409. |
| GET | /pending | { "pending": … }, the queued prompt, if any. |
| GET | /prompts | { "prompts": [{ "type", "event" }] }, the prompts a prompt-receiving /submit stream forwarded that are still open, oldest first. |
| POST | /prompts/:id | Answers an open prompt: { "result": true | false | "allow-session" | "allow-project" } for a permission, { "response": { "type": "answer", "values": string[], "text"?: string } | { "type": "cancelled" } } for an ask. 404 when the id is not open, 400 for an answer of the wrong shape, 409 when the session did not take the answer. |
Permission and ask prompts
A turn can stop to ask whether a tool may run (permission_request) or to ask the user a question
(ask_request). Only a client that says it can answer receives them: send receivePrompts: true with
/submit, and answer each prompt by its event.id through POST /prompts/:id. prompt_resolved
follows when a prompt is settled, by this client or by another surface on the same session. A
client that comes later reads the open prompts from GET /prompts and answers the same way.
Without receivePrompts, nothing changes: a turn whose prompt no surface can answer is denied (or the
question cancelled) at once rather than left waiting. Closing the stream aborts the turn, which settles
its open prompts the same way. The answer is recorded as the host's attribution.driverId, never as
anything the request claims.
Paths are relative to where the routes are mounted (basePath, or the prefix you pass to
app.route).
Exports
| Symbol | Kind | Description |
|---|---|---|
createHttpTransport | function | (options?: IHttpTransportOptions) => IHttpTransport |
createAgentRoutes | function | (options: IAgentRoutesOptions) => Hono |
IHttpTransportOptions | interface | { basePath?, admission?, onStreamFailure?, attribution? } |
IHttpTransport | interface | The transport; adds getApp() and getAdmissionToken() to the standard transport lifecycle |
IAgentRoutesOptions | interface | { sessionFactory, admission, onStreamFailure?, attribution? } |
TSessionFactory | type | (c: Context) => IHttpTransportSession | Promise<IHttpTransportSession> |
IHttpTransportSession | interface | The session capabilities the routes use; a full interactive session satisfies it |
TTurnAttribution | type | Host-assigned driverId/surface for turns and prompt answers; never read from the request |
TStreamFailureListener | type | Receives the details of a stream that fails after headers were sent (the client sees a generic error) |
Related
@robota-sdk/agent-transport— the admission helpers and the prompt-answer decoder these routes use.@robota-sdk/agent-transport/ws— the WebSocket transport, which carries the full session protocol (this HTTP surface covers a subset).- docs/SPEC.md — package contract and invariants.