Skip to content

Steerable

The model-quality layer that makes local, quantized, and cheap models behave.

Fewer hallucinations Simple to use Ready out of the box Componentized

Fewer hallucinations, fewer silent failures — even on cheap models. 79.0% on Terminal-Bench 2.1 with GLM-5.3-Flash. One command boots a full agent shell; every layer underneath ships as its own package, so you adopt only what you need.

License: Apache 2.0 CI npm: @steerable/agent-ui PyPI: steerable-agent-runtime

79.0% Steerable + GLM-5.3-Flash TB 2.1 · 3-run mean @max · this repo

+5.6 vs Pi on the same Flash model Pi + GLM-5.3-Flash · 73.4%

229.9M input tokens per catalog run three-run mean · 15.4% below prior baseline

Simple to start

A full agent in one command

Chat, an integrated terminal, bundled skills, a model picker, and a sandboxed sidecar, ready on first launch. Run it in the browser, as a desktop app, or from the command line — same shell, same data. Bring any OpenAI-compatible, Anthropic, or Gemini key.

More ways to install
git clone https://github.com/pathlyapp/steerable.git
cd steerable && pnpm install
pnpm agent-shell:web
→ Steerable Shell listening at http://127.0.0.1:4787
git clone https://github.com/pathlyapp/steerable.git
cd steerable && pnpm install
pnpm agent-shell:client
→ Steerable Shell opens in its own Electron window
npm install -g @steerable/agent-cli
steerable-cli
→ steerable-cli opens a terminal session. Node 26.4.0.

Frontier results on Flash-priced models

Terminal-Bench 2.1, 89 real terminal tasks, hidden tests; timeouts count as fail. Same models, same protocol, five agent harnesses. Methodology

Pass rate · three Flash models · five harnesses

Tasks solved out of 89. Color is the harness.

0 25 50 75 89 79.8 73.0 77.5 56.2 66.3 GLM @high 78.7 69.7 44.9 61.8 77.5 DS0731 @high 68.5 62.9 70.8 64.0 60.7 Qwen @medium Steerable Pi Claude Code Codex DSH

One run per cell at high effort (Qwen: medium). Run list and commit SHAs

Score vs cost per solved task

Color is the harness; shape is the model (circle GLM, square DeepSeek, diamond Qwen). Higher and further left is better.

$0.10 $0.25 $0.50 $1 $2 $5 45 55 65 75 80 $ per solved task (log) · OpenRouter list on pinned host TB 2.1 score (n=1 pass / 89) Pi · GLM 73.0% · $0.12 Claude Code · GLM 77.5% · $0.23 Pi · DS 69.7% · $0.28 Steerable · GLM 79.8% · $0.61 Claude Code · DS 44.9% · $0.85 Codex · GLM 56.2% · $1.06 Claude Code · Qwen 70.8% · $1.68 Steerable · DS 78.7% · $2.18 Codex · Qwen 64.0% · $2.60 Pi · Qwen 62.9% · $2.87 Steerable · Qwen 68.5% · $4.12 Codex · DS 61.8% · $4.42 DSH · GLM 66.3% · $0.12 DSH · DS 77.5% · $3.48 DSH · Qwen 60.7% · $3.36 Steerable Pi Claude Code Codex DSH circle GLM · square DeepSeek · diamond Qwen

OpenRouter list prices on the pinned host. Pricing formula

GLM-5.3-Flash @high, same run as the charts: Steerable 79.8% · Claude Code 77.5% · Pi 73.0% · DSH 66.3% · Codex 56.2%.

Why Steerable

Cheap models invent data, claim work they never did, and emit tool calls as plain text. Every agent SDK assumes they don't. Steerable checks the model at each of those points — and stays out of your way.

01 · Fewer hallucinations

Answers backed by real data

Grounding judges reject answers the tool results don't support, a discipline retry catches claimed-but-undone work, and a completion veto can send a draft back before it reaches the user. Tool calls written as text are recovered and executed. On the DeepPath API this turns a class of 646 hard failures into retries.

02 · Simple to use

Learn it in an afternoon

No graph DSL or framework runtime to learn. Tools are plain functions with an @tool decorator, the harness is pure functions with zero I/O, and one JSON Schema generates both the TypeScript and Python types.

03 · Ready out of the box

Everything already wired up

Chat, terminal, skills, model picker, and an OS sandbox with a per-host egress allow-list come preconfigured. The hosted live demo runs in the browser with no key at all.

04 · Componentized

Take one layer, skip the rest

Five tiers and 13 independently published packages. Lower tiers never import higher ones, so you can use only the protocol types, only the React UI, or only the sidecar without pulling in anything else.

What's inside

The model-quality layer

Local, quantized, and cheap models break the structured-tool_calls assumptions every SDK makes. Steerable recovers and executes malformed calls (MiniMax XML, DeepSeek <function=>, markdown), vetoes completion drafts (accept / retry / narrate), judges grounding, and self-calibrates token estimates. Why this is the differentiator.

One wire protocol

One JSON Schema → generated TypeScript types + Pydantic models. content, tool_call, tool_result, error, done, budget_exhausted — all standardised, with a conformance suite keeping both SDKs byte-compatible. All 13 published packages share one lockstep X.Y.Z (including the Rust CoreLoop wheel); npm tarballs ship sigstore provenance attestations.

Pure-function harness

Policy, budget, retry, completion, tracing, safety patterns. Zero I/O coupling — drop into FastAPI, Celery, or a notebook. Unit and golden tests in CI.

Pluggable runtime

One LLMProvider interface across four wire protocols — OpenAI-compatible chat/completions (Ollama, vLLM, DeepSeek, Groq, …), OpenAI Responses, Anthropic-native, Gemini-native — plus a live gateway model catalog, per-vendor sampling presets, @tool decorator, ToolRouter, SSE-over-HTTP and stdio JSON-RPC transports.

Embeddable sidecar

A portable, signed CPython binary speaking JSON-RPC over stdio (34 methods). Ship local LLMs inside Electron / Tauri / Wails — macOS notarised, Windows code-signed — with an OS sandbox, per-host egress proxy, and plugin lifecycle built in.

Headless React UI & Web Shell

7 components + 14 rich cards + 3 hooks + Tailwind preset, each state covered by Storybook, axe a11y, and visual-regression baselines in CI. The same components power the full Web Shell (pnpm agent-shell:web).

Quickstart — pick your path

git clone https://github.com/pathlyapp/steerable.git
cd steerable && pnpm install

pnpm agent-shell:web      # full agent shell → http://127.0.0.1:4787
pnpm agent-shell:client   # same shell as a desktop (Electron) window

Chat, integrated terminal, bundled skills, model picker, and a Seatbelt-sandboxed sidecar, all on the production code path. Add your model endpoint in settings and start working.

Only want to explore the UI? pnpm shell:dev opens a UI-only reference app on http://localhost:5180 that replays all 14 rich cards from sample data, with no backend or API key.

uv add steerable-agent-protocol steerable-agent-harness steerable-agent-runtime
from steerable_agent_runtime import ToolRouter, tool
from steerable_agent_protocol import ToolCall

router = ToolRouter()

@tool(router=router, description="Read a file by path")
async def read_file(path: str) -> dict:
    return {"path": path, "content": open(path).read()}

result = await router.dispatch(
    ToolCall(id="c1", name="read_file", arguments={"path": "README.md"})
)
# result.success, result.data, result.error — all typed.
pnpm add @steerable/agent-protocol @steerable/agent-ui
import { ChatPanel, useChatStream } from '@steerable/agent-ui';

export function Chat() {
  const { messages, send, isStreaming } = useChatStream({
    endpoint: '/api/chats/123/send',
  });
  return <ChatPanel messages={messages} onSubmit={send} isStreaming={isStreaming} />;
}
# Bundle the sidecar binary into resources/python-runtime/<platform>/
# TS hosts: link:../steerable/packages/agent-runtime/ts
import { AgentRuntime } from '@steerable/agent-runtime';

const runtime = new AgentRuntime({ sidecarPath });
await runtime.start();   // spawn + lifecycle.ready handshake

const stream = await runtime.chatStream({
  provider: 'openai_compat',
  model: 'glm-5.3-flash',
  baseUrl: process.env.GATEWAY_BASE_URL!,
  apiKey: process.env.GATEWAY_API_KEY!,
  messages: [{ role: 'user', content: 'hi' }],
});
for await (const event of stream.events) { /* typed SSEEvent stream */ }

Architecture

Five tiers, strict no-upward-imports rule. Tier N never imports Tier N+1 — adopting any layer means inheriting only the layers below it.

graph BT
  T5["<b>Tier 5 · Host Shell</b> (TypeScript, private)<br/>@steerable/agent-shell · agent-shell-web · pack-sdk<br/>Electron main + headless HTTP server · local backend ·<br/>sidecar supervision · product-neutral renderer SPA"]

  T4["<b>Tier 4 · UI</b> (TypeScript / React)<br/>@steerable/agent-ui<br/>Hooks: useChatStream · useToolCallStatus · useAgentSession<br/>Components: ChatPanel · MessageList · AgentSelector · ModelSelector ·<br/>OrchestrationPlanCard · ToolCallRenderer · SSEStreamView + 14 cards<br/>Tailwind preset (dark-mode aware)"]

  T3S["<b>Tier 3 · Sidecar</b> (portable CPython binary)<br/>steerable-sidecar<br/>JSON-RPC over stdio · 34 methods · graceful shutdown<br/>agent.chat.stream · tool.invoke · agent.session.* · plugin.* · models.list"]

  T3R["<b>Tier 3 · Runtime</b> (Python only)<br/>steerable-agent-runtime<br/>CoreLoop · LLMProvider (OpenAI-compat / Responses / Anthropic / Gemini)<br/>ToolRouter · StorageAdapter · TransportAdapter (FastAPI SSE)"]

  T2["<b>Tier 2 · Harness</b> (Python — single source of truth)<br/>steerable-agent-harness<br/>Policy · Budget · Retry · Completion · Tracing · Safety<br/><i>thin TS facade @steerable/agent-harness exists for parity tests</i>"]

  T1["<b>Tier 1 · Protocol</b> (TypeScript + Python, lock-step versions)<br/>@steerable/agent-protocol · steerable-agent-protocol<br/>SSEEvent · ChatMessage · ToolCall · ToolResult · AgentSession<br/>HarnessTrace · TraceSpan · SidecarRequest/Response/Notification"]

  T5 -->|"spawns + supervises"| T3S
  T5 -.->|"renders with"| T4
  T4 -.->|"shared wire types"| T1
  T4 -->|"spawns + JSON-RPC stdio (Electron)"| T3S
  T3S -->|"embeds"| T2
  T3S -->|"validates against"| T1
  T3R -->|"embeds"| T2
  T3R -->|"validates against"| T1
  T2 -->|"imports types"| T1

What's in the box

Package Tier What you get
@steerable/agent-protocol · steerable-agent-protocol 1 SSEEvent envelope, ToolCall / ToolResult, ChatMessage, sidecar JSON-RPC types — codegen from spec/, drift-checked in CI
@steerable/agent-harness · steerable-agent-harness 2 decide_tool_mode, consume_budget, next_retry_delay_ms, is_terminal_result, command-safety patterns
steerable-agent-runtime · @steerable/agent-runtime (TS, source-only) 3 CoreLoop + LLMProvider adapters (OpenAI-compat / Responses / Anthropic / Gemini), ToolRouter + @tool, storage & transport adapters (FastAPI SSE, stdio JSON-RPC); the TS package owns the sidecar process lifecycle for pure-TypeScript hosts
steerable-sidecar · steerable-egress-proxy 3 Portable CPython binary — boots in <1s, macOS notarised, Windows signed — plus the bundled per-host CONNECT allow-list egress proxy
@steerable/agent-ui 4 ChatPanel, MessageList, AgentSelector, ModelSelector, OrchestrationPlanCard, ToolCallRenderer, SSEStreamView + 14-card /cards subpath + hooks + Tailwind preset
@steerable/agent-shell · agent-shell-web · agent-shell-tauri · pack-sdk 5 Tauri + headless host shell, shared Node HostRuntime, sidecar supervision, product-neutral renderer — published to npm (dist / source / pure-types respectively)
@steerable/agent-cli 5 Product-neutral command line and terminal session. npm install -g @steerable/agent-cli, then steerable-cli. It shares the host database with the desktop app.

How it compares

Steerable isn't the only way to ship an agent. The short, honest version against the frameworks you're probably also evaluating:

Dimension Steerable OpenAI Codex DeepSeek Harness LangGraph OpenAI Agents SDK Claude Code / Agent SDK
Form factor Layered library — the same loop in a desktop sidecar and a server Product family: CLI, IDE, desktop, cloud — Rust core Plugin-based harness (TS) on Cordis Orchestration library — you write the graph Lightweight framework over the Responses API One closed-source bundle behind both the CLI and the Agent SDK
Loop / events CoreLoop + structured LoopEvent taxonomy; mid-turn agent.chat.steer Session-owned turn loop; interrupt/abort; 12-event hooks Inbox-driven ReactLoop; steer / inject / followup Interrupts at node boundaries Handoffs + guardrails; no mid-run steer Mid-turn fold queue; hooks can veto continuation
Sandbox Seatbelt + bwrap/Landlock, fail-closed; command classifier; per-host egress proxy Approvals + ExecPolicy + Seatbelt/Landlock + Guardian sandbox.confine, fail-closed None built-in Guardrails; no sandbox Permission modes; Seatbelt/bwrap opt-in, fail-open
Model quality Recovers malformed tool calls; completion veto; grounding; token calibration Assumes structured tool_calls Assumes structured tool_calls Substrate — you own the loop Built for frontier models Built for frontier models
Maturity 0.6.x; used in production deployments Massive real-world usage Pre-release (0.1.x); internal use Widely adopted in production Production, OpenAI-tied Production; Anthropic models via first-party, Bedrock, Vertex, Foundry, Gateway

Where Steerable genuinely differs, where it lags, and how to choose: Full comparison.

Who's using it

Enterprise & Products
Research & Universities
Tsinghua University Tsinghua University
University of Chinese Academy of Sciences UCAS

Explore