Build Your Own Harness with the Agent SDK

We built a skill for building your own agent harness and terminal UI (TUI). It walks you through four different ways of customizing the look, and supports dozens of optional features: custom banners, multiple tool display styles, and input fields you can match to Codex's style or Claude Code's style.
Point Claude Code, Codex, Cursor, or any skill-compatible agent at create-agent-tui, describe what you want, and it generates a complete, runnable TypeScript project. The whole thing runs on the recently launched Agent SDK and works with any model on OpenRouter.
Why do this when there are many great commercial harnesses out there?
- You want fine-grained control over the look, tools, or the loop
- You want a minimal harness you can ship as part of a product
- You want to learn how agents work to get better at using and debugging them

Try building your own now
- Get an OpenRouter API key if you don't have one
- Install the create-agent-tui skill in your coding agent
- Tell your agent to build you a coding assistant and what will make your assistant unique
- Run
pnpm install && pnpm startin the generated project
The skill presents an interactive checklist when invoked. You pick what you need: server tools (web search, datetime, image generation), local tools (file read/write/edit, grep, glob, shell, and more), harness modules (session persistence, context compaction, tool approval gates), and slash commands (/model to switch models on the fly, /new for fresh conversations, /export to save as Markdown). After you make your selections, it generates the full project and verifies types with tsc.
Every part of the terminal UI is customizable out of the box. Three tool display styles (emoji markers, grouped action labels, or minimal one-liners), three input styles (full-width block that adapts to your terminal theme, bordered lines, or plain readline), three loader animations (gradient shimmer, spinner, or trailing dots), and custom ASCII banners. You can also describe what you want directly and the skill will generate a custom style.
The generated project is yours to modify. Add domain-specific tools, wire up a different entry point (the skill includes templates for HTTP API servers), bolt on context compaction for long conversations, or strip it down to the bare minimum.
The skill relies on the Agent SDK for a trustworthy inner loop
The skill generates two layers of code. The inner layer is the Agent SDK: one callModel call that handles the entire agentic loop (model calls, tool execution, multi-turn cycling, stop conditions, streaming, cost tracking). The outer layer is everything the skill generates around it: configuration, tool definitions, session management, the TUI, and the entry point.
Here's the generated src/agent.ts, stripped to the essentials:
That single callModel call is the entire agent loop. The SDK calls the model, inspects the output for tool requests, validates arguments against your Zod schemas, executes the tools, feeds results back, and repeats until a stop condition fires.
The skill wires up streaming on top of this by iterating over result.getItemsStream(). Each item is typed and carries the complete current state: message items carry the full assistant text so far, function_call items carry tool invocations, function_call_output items carry results, and reasoning items carry model thinking. The generated src/renderer.ts turns these into a clean terminal display with token counts and tool call summaries.
Tools live in src/tools/, one file per tool. Each tool uses the SDK's tool() function with a Zod schema for input and a typed execute function. Server tools (web search, datetime) are even simpler: serverTool({ type: 'openrouter:web_search' }) and OpenRouter executes them server-side with zero client code.
Configuration flows through three layers: hardcoded defaults, an optional agent.config.json file, and environment variables. You can set your preferred model and cost limits in a config file and override them per-session with AGENT_MODEL=openai/gpt-5 npm start.
Session persistence writes every message to a JSONL file. On the next run, the harness can reload conversation history and pass it back into callModel as an Item[] array, picking up where you left off.
These patterns come from the top harnesses
The skill draws from three production agent architectures:
- pi-mono's coding agent: three-layer separation (config, agent loop, tools), JSONL sessions, pluggable tool operations
- Claude Code: tool metadata with read-only and destructive flags, system prompt composition from static and dynamic context
- Codex CLI: layered configuration (defaults, config file, environment variables), approval flows with session caching
These patterns are baked into the generated code, but the Agent SDK is what makes the whole thing compact. Without callModel handling the agentic loop, tool validation, streaming, and cost tracking, you'd be writing hundreds of lines of loop management code yourself. The skill focuses entirely on the app-specific parts because the SDK handles everything else.
For the full callModel API reference, check the SDK docs. To build your own skills on top of the Agent SDK, start with the skills repo.