UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

95 lines (94 loc) • 5.44 kB
/** * session — the session strategies: which AgentCore Runtime session a request * lands in. * * ── The facts they rest on ─────────────────────────────────────────────────── * From the AgentCore Runtime MCP protocol contract and the `InvokeAgentRuntime` * API reference: * * - The runtime routes by `Mcp-Session-Id` and always returns one. A client * "must capture the Mcp-Session-Id returned in the response and include it * in all subsequent requests" for microVM affinity; without it "each request * may be routed to a new microVM". * - `InvokeAgentRuntime` also carries `runtimeSessionId` * (`X-Amzn-Bedrock-AgentCore-Runtime-Session-Id`, 33–256 characters), and * the AWS SDK models it as an idempotency token — it fills a FRESH random id * on every call that leaves it unset. * * ── 'per-call' (the default) ───────────────────────────────────────────────── * Every request in a session of its own: this strategy sends a FRESH runtime * session id with every request and no `Mcp-Session-Id`, and the * `Mcp-Session-Id` a response carries is not handed to the MCP client, so * nothing can carry one call's session into the next. Isolation by * construction: a client shared by every user of a process (tools built once at * startup — the common shape) never puts two users in one microVM. The price is * a cold start per call, and it needs a STATELESS server (`stateless_http=True`, * the runtime's recommended default) — a stateful one sees every request as a * stranger. * * ── 'reuse' ────────────────────────────────────────────────────────────────── * One session per CONNECTION (per `mcpClient` built on the transport), and the * TRANSPORT owns the key. A request with no `Mcp-Session-Id` (a client's * `initialize`) opens a connection with a fresh runtime session id; the * `Mcp-Session-Id` the server returns for it is stored WITH that connection, * and the client is handed an opaque handle of the transport's own in its * place. Every later request carrying the handle is sent in that connection's * runtime session with the server's own id. A handle the transport does not * know — one it never issued, or one it forgot — is never sent: the request * fails with `LocalSessionHandleLostError`, thrown from the transport's * `fetch`. It is not a 404: no server said anything, and the runtime session * behind a forgotten handle may still run — it can no longer be stopped from * here, because its id went with the handle. * * Why a handle and not the server's id: the server's ids are unique only as far * as the server makes them. One that numbers sessions per process hands every * fresh microVM the same first id, and a map keyed by it would send the second * client into the first one's microVM. A handle is ours, random, and per * connection, so two clients on one transport are two sessions whatever the * server returns — while ONE client is still one session for whoever calls * through it. Build a client per conversation; never share a 'reuse' client * between users. * * At most {@link MAX_CONNECTIONS} connections are remembered, least recently * used forgotten first. A client's `DELETE` — sent by `terminate()`, never by * `close()`, which ends only the local side — forgets its own handle first, and * then becomes `StopRuntimeSession` for that connection's runtime session * (`transport.ts`), answered like a server would answer the `DELETE`. * * Pattern: Strategy. Role: outer ring, vendor fact. Holds no credential. */ /** The runtime session header, as `InvokeAgentRuntime` binds `runtimeSessionId` to it. */ export declare const AGENTCORE_RUNTIME_SESSION_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"; /** The MCP Streamable HTTP session header. */ export declare const MCP_SESSION_HEADER = "Mcp-Session-Id"; /** Which session a request lands in. See the module note for each. */ export type AgentCoreRuntimeSession = 'reuse' | 'per-call'; /** * What a strategy does with one request: answer it here, unsent; let it go — * with its session headers fixed in place — and say what the MCP client may see * of the response; or, for a `'reuse'` connection's `DELETE`, stop that * connection's runtime session (`stop`, its runtime session id). */ export type SessionStep = { readonly answer: Response; } | { readonly settle: (response: Response) => Response; } | { readonly stop: string; }; /** One strategy, applied once per request the MCP client makes. */ export interface SessionStrategy { /** * @throws `LocalSessionHandleLostError` for a handle this strategy does not * hold: nothing is sent */ request(headers: Headers, method: string): SessionStep; } /** How many connections a 'reuse' transport remembers before it forgets the least recently used. */ export declare const MAX_CONNECTIONS = 256; /** * Build the strategy for one transport. * * @throws when `kind` is not one of the two strategies. */ export declare function sessionStrategy(kind: AgentCoreRuntimeSession): SessionStrategy;