Skip to main content
Agent Forge (apps/agent-forge) is this SDK’s companion visual dashboard: build an agent’s graph on a canvas, run it, watch it execute in a live debug console, chat with it, and author sandboxed pre/post hooks - all reading and writing the exact same AgentSpec YAML that lousho dev and lousho build use. It’s launched with one command, lousho studio, and ships as part of this SDK’s npm package (LOU-S). This doc covers: installation, the lousho studio quickstart, a first-agent walkthrough, hook authoring, time travel (replaying a run from a past step), and how settings/secrets/deploy wiring works (and doesn’t yet).

Installation

Agent Forge ships inside @lousho/build-ai-agent itself - there’s no separate package to install:
That’s it. lousho studio (below) runs a pre-built copy of the app; you don’t need apps/agent-forge’s own source or its devDependencies (Vite, tsx, etc.) to use it. If you’re working inside this SDK’s own monorepo instead (contributing to Agent Forge itself), see Dev mode below.

Quickstart

This starts one local server and prints its URL (default http://127.0.0.1:4750). Open it in a browser - you’ll see the canvas, the left rail (your saved agents + a node/hook palette), the Inspector (right), and a bottom drawer with Chat/Logs/Trace/Output/Settings tabs. Useful flags:
Agent specs and run state are stored under .lousho/ in the directory you ran lousho studio from (agent YAML files under .lousho/agents/, checkpoints and approvals alongside them) - the same .lousho/ layout lousho dev/lousho build use.

Production vs. dev mode

lousho studio has two modes, and picks the right one automatically:
  • Production (the default once Agent Forge has been built): a single Express server serves both the REST/WebSocket API and the pre-built client (React app) as static files, on one port. This is what runs when you npm install the published package - there’s no separate Vite dev server and no TypeScript loader involved.
  • Dev (falls back to this if the build hasn’t been run yet, i.e. inside a source checkout of this monorepo): the API server runs straight off its TypeScript source via tsx, alongside a real Vite dev server (with hot-module reload) that proxies API requests to it. Two processes, two ports internally, one command.
--prod/--dev force one or the other; run without either flag and lousho studio auto-detects based on whether apps/agent-forge/dist-server exists.

First-agent walkthrough

  1. Create an agent. In the left rail’s “Agents” tab, click New, give it a name, and pick a starting template - Blank graph (a single LLM node using the built-in mock provider) is the fastest way to try things out without any API keys. Agent Forge creates the agent and opens it on the canvas.
  2. Look at the graph. A blank agent is one llm node. Drag more nodes in from the left rail’s palette (Trigger, LLM step, Tool call, Approval gate, Response / output) and connect them by dragging between their handles. Click a node to edit its settings (prompt, provider/model, tools, breakpoints) in the Inspector on the right.
  3. Run it. Click Run in the top bar. With the mock provider there’s nothing to configure - it returns deterministic canned output, which is exactly the point for trying the rest of the UI without needing a real LLM API key. The status pill in the top bar tracks the run (running → idle/error/awaiting approval).
  4. Watch it in the debug console. Open the bottom drawer’s Logs tab for a live, filterable log feed of the run (trigger/llm/tool/ sandbox/checkpoint/approval events), or Trace for a span waterfall. Turn on Debug in the top bar (or set a breakpoint on a node in the Inspector) to pause the run at LLM/tool boundaries and step through it with the debug bar’s Step/Continue controls; expand “Live message array” there to inspect the in-flight message list. Output shows the full ExecutionResult (messages, tool calls, usage, steps) as a collapsible JSON tree once the run finishes or pauses.
  5. Chat with it. The Chat tab is a separate conversational transport (POST /agents/:id/message, streamed back over the same WebSocket as everything else) - send it a message and it replies in the thread, independent of the graph “Run” button above. Each agent keeps its own chat history (+ New chat starts a fresh session; old ones stay browsable).
  6. Approve a paused tool call. Add a Tool call node, open it in the Inspector, and pick a tool - some tools (or an agent’s own policy) can require human approval before running. When a run or chat hits one, an inline approval card appears (in the top bar for a graph run, or as a message bubble in the Chat thread) showing the tool name and its arguments. Click Approve to let it proceed or Reject to abort that call; the run resumes automatically either way.

Hooks

Hooks (LOU-Q) are small, sandboxed functions that run immediately before or after a tool call or an LLM generate - the same mechanism the SDK core exposes as HookRegistry/AgentHook (see API Overview), but authored visually and attached to a specific canvas node. To attach one:
  1. Select an llm or tool node on the canvas (hooks only apply to these - they’re the two points AgentExecutor actually calls out to).
  2. Open the Inspector’s Hooks section. Drag a Pre-hook or Post-hook entry from the left rail’s palette onto the node (or drop it directly in the Hooks section) to attach a new one; you’ll get a choice of starter templates (redact-pii, rate-limit, audit-log, inject-context) as an editable starting point.
  3. Click the hook’s chip to select it, then edit its code in the CodeMirror editor. The code is the body of an async function invoked as hook(ctx) inside a sandboxed subprocess (server/hookSandbox.ts) - never in the browser or the API server process itself:
    • For a tool-call hook, ctx is { toolName, args, result?, error? }. A pre-hook can mutate ctx.args; a post-hook can inspect/mutate ctx.result/ctx.error. Return ctx.
    • For an LLM-generate hook, ctx is { messages, model }. Mutate/push onto ctx.messages and return ctx.
    • Throwing aborts the step - a rate-limit hook, for example, throws to block the tool call outright rather than letting it run.
  4. Toggle the switch on a hook’s chip to enable/disable it without removing it, or use its x to remove it entirely. Only enabled hooks are compiled into the run.
Example: a redact-PII pre-hook on a tool node (this is the redact-pii starter template) -
Saving the agent persists these as spec.policy.hooks in the agent’s YAML; the server compiles enabled hooks into a real HookRegistry for the run (server/compileHooks.ts), routed through the same SandboxAdapter a sandboxed tool uses.

Time travel

Agent Forge keeps every run’s checkpoints, not just the latest: its file store (server/checkpointStore.ts) keeps the same bounded history as the SDK’s LocalStorageCheckpointStore (the newest 50 saves per run, under .lousho/agents/<id>/checkpoint-history/; see Checkpoint history). From that history you can fork a run at any step, change what happened there, and replay it next to the original, with AgentExecutor.fork() and compareTrajectories() doing the work.

The History tab

  1. Run the agent (Topbar Run, or a Chat message).
  2. Open the bottom drawer’s History tab. It lists the run’s steps: step number, status, the model’s finish reason, the tool calls made, and the tokens and cost of the step’s model call when known.
  3. Click Edit and replay from here on a step. Choose Append a user message and type one, or pick one of the step’s tool calls to edit its result (prefilled with the recorded result; text that parses as JSON is sent as JSON).
  4. Click Fork and replay. The run is forked at that step with your edit and started as a new run, <id>.fork-<n>.
  5. The fork opens next to the original as a side-by-side trajectory: each model turn of both runs (text, tool calls and results), the first turn where they differ highlighted as diverged, and the drift entries (tool order, arguments, step count, finish reason) listed below. It refreshes when the fork finishes.

Routes

A run id is the run’s checkpoint session id: the agent id for the agent’s own runs, <id>.fork-<n> for a fork of run <id>. The runtime control server has three routes for it (the History tab uses them): The flow, for an agent weather that has run once:
The fork is a run of its own: the original run’s checkpoints, status and chat are unchanged.

Settings, secrets and deploy wiring

The bottom drawer has a Settings tab with three parts: provider API keys (OpenAI and Anthropic, stored encrypted under .lousho/ and never shown again), named settings profiles (provider, deploy adapter, hook timeout, OpenTelemetry toggle; kept in .lousho/settings.json, which holds no secrets), and a Deploy section that picks an adapter (node-server, docker or cloudflare-worker) and runs lousho build for the selected agent. Other providers still read their environment variables, the same way lousho dev/lousho build do (see Configuration), and the mock provider needs no credentials.

Dev mode

If you’re working inside this SDK’s own monorepo (contributing to Agent Forge itself, not just using it), lousho studio falls back to dev mode automatically as long as apps/agent-forge/dist-server hasn’t been built yet:
This runs the API server straight from TypeScript (tsx) and a real Vite dev server with hot-module reload for apps/agent-forge/src/**, as two sibling processes. To build the production bundle used by everyone else (and to verify what actually ships):
npm run build:studio also runs automatically as part of the root prepublishOnly script, so a published npm publish can never ship a stale or unbuilt studio.

E2E smoke test

apps/agent-forge/e2e/studio.spec.ts is a headless Playwright test that drives the real, built lousho studio (the same dist-server/index.cjs production server, not a dev-mode Vite server) through a browser: it creates an agent from the “Support bot” template, retargets its tool node at a server-local demo-approval tool (always needsApproval: true - see server/buildAgent.ts’s doc comment for why this exists, since none of the SDK’s spec-resolvable built-in tools require approval), sends it a chat message that triggers the mock provider’s tool-call heuristic, waits for the run to pause on the approval gate, approves it via the Chat tab’s inline approval card, and asserts the run completes. Run it with:
This builds Agent Forge first (build:studio), then runs Playwright against it.