A foundational starter kit for building task-specific autonomous AI agents.
Clone this repository, describe the capabilities you want to your coding assistant, and let it generate the tools and prompts. The execution loop, streaming dashboard, and safety controls are already wired up.
Whenever you want to build an AI agent for a specific task (DevOps, database operations, file transformations, web scraping, server management, personal assistant), 70% of the work is repetitive boilerplate plumbing:
- Writing the multi-turn tool execution loop and managing token context limits
- Wiring Server-Sent Events (SSE) with heartbeat pings and event buffers for late connections
- Building a browser interface to view the agent's actions and text responses
- Parsing reasoning tokens (
thought,reasoning_content, and<think>...</think>tags) from thinking models - Working around upstream model quirks (such as Gemini emitting concatenated JSON chunks or repeating tool names)
- Adding confirmation dialogs for destructive actions
- Implementing provider switching between OpenAI, OpenRouter, Groq, and local Ollama or LM Studio models
Agent Base provides all of that plumbing in one place. Instead of building infrastructure from scratch, you or your coding assistant add domain-specific tools, set the system instructions, and start using the agent right away.
Open this repository in your AI coding assistant (Cursor, Claude Code, Windsurf, Copilot, or OpenCode) and ask it to adapt the codebase:
"Turn this repository into a Docker manager agent that inspects running containers, reads logs, restarts services, and prunes unused images. Require confirmation before pruning images."
"Turn this repository into a GitHub pull request reviewer that lists open pull requests, fetches diffs, checks for security issues, and posts comments."
"Turn this repository into a crypto portfolio agent that fetches prices from CoinGecko, checks wallet balances, and calculates 24-hour profit and loss."
"Turn this repository into a research agent that searches the web, extracts key details from articles, and saves markdown summaries."
Your coding assistant reads AGENTS.md, registers tools in src/agent/tools.js, updates the instructions in src/agent/systemPrompt.js, updates the sample prompts in the interface, runs the test suite, and gives you a working agent.
Click the Use this template button at the top of the GitHub page to create your own repository, then clone it:
git clone https://github.com/YOUR_USERNAME/YOUR_AGENT_NAME.git
cd YOUR_AGENT_NAME
npm installOr clone Agent Base directly:
git clone https://github.com/walsoup/agent-base.git
cd agent-base
npm installCopy the environment template:
cp .env.example .envSet your provider details in .env (or configure them in the browser using the Setup & Config button):
OPENAI_API_KEY=your-api-key-here
OPENAI_MODEL=gemini-3.7-flashnpm startOpen http://127.0.0.1:3700 in your browser.
The web dashboard comes with 5 switchable themes accessible from the top bar or via the data-theme attribute:
| Theme | Key | Aesthetic |
|---|---|---|
| Midnight Dark (Default) | dark |
Deep slate gray and blurple |
| OLED Black | oled |
Pure pitch-black with emerald accents |
| Catppuccin Mocha | catppuccin |
Warm pastel mauve and lavender |
| Nord Frost | nord |
Arctic icy blues and cool slates |
| Paper Light | light |
Crisp high-contrast editorial light theme |
Selected themes persist in localStorage. You can add custom palettes in public/style.css by defining a new [data-theme="your-theme"] block with CSS variables.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Web Dashboard (UI) β
β β’ Model picker & presets β’ Live SSE stream reader β
β β’ Chain-of-thought view β’ Batch progress bars β
β β’ Resource explorer β’ Theme switcher (5 looks)β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β HTTP / SSE
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β Express Server β
β β’ /api/chat β’ /api/stream/:id β’ /api/approve β
β β’ /api/state β’ /api/config β’ /api/dry-run β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β Autonomous Agent Loop β
β β
β 1. Build dynamic system prompt from current state β
β 2. Query model (OpenAI, OpenRouter, Groq, Ollama) β
β 3. Stream text, reasoning tokens, and tool calls β
β 4. Clean tool names and repair malformed JSON β
β 5. Validate arguments with Zod schemas β
β 6. Pause for user approval on destructive actions β
β 7. Run tool handler (with live progress events) β
β 8. Store results in history and repeat until finish β
ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββ΄βββββββββββββββ
β β
βββββββββββΌββββββββββββ βββββββββββΌββββββββββββ
β Agent Tools β β State Store β
β Add your custom β β Connect to your β
β tools in tools.js β β database or files β
βββββββββββββββββββββββ βββββββββββββββββββββββ
agent-base/
βββ AGENTS.md # Instructions for coding assistants adapting this project
βββ package.json # Node dependencies (Express, OpenAI, Zod)
βββ .env.example # Environment template
βββ .gitignore # Git exclusion rules
βββ README.md # Project documentation
βββ src/
β βββ server.js # Web server and API endpoints
β βββ agent/
β β βββ loop.js # Multi-turn loop, streaming, and approval logic
β β βββ tools.js # Tool registry (where domain skills are added)
β β βββ systemPrompt.js # Dynamic system prompt generator
β β βββ config.js # Provider configuration (OpenAI, Groq, Ollama)
β βββ state/
β β βββ state.js # Environment state store and dry-run flag
β βββ util/
β βββ sse.js # SSE manager with heartbeats and replay buffers
β βββ log.js # Audit logging to daily JSONL files
β βββ env.js # .env persistence utilities
βββ public/ # Browser interface (with theme switcher)
βββ test/
βββ verify.js # Unit verification suite (run with npm test)
Register tools in src/agent/tools.js using registerTool. You only need a Zod schema; Agent Base derives the OpenAI JSON schema automatically:
import { z } from 'zod';
import { registerTool } from './agent/tools.js';
registerTool({
name: 'restart_service',
description: 'Restart a system service or background worker',
destructive: true, // Prompts for confirmation when live mode is active
schema: z.object({
service_name: z.string().describe('Name of the service to restart')
}),
handler: async (args) => {
return { ok: true, result: `Service ${args.service_name} restarted.` };
}
});Batch tools can report progress back to the interface using the context.onProgress callback:
registerTool({
name: 'batch_convert_files',
description: 'Convert a list of files with live progress feedback',
destructive: false,
schema: z.object({
files: z.array(z.string().min(1)).describe('Files to convert')
}),
handler: async (args, { onProgress }) => {
const total = args.files.length;
for (let i = 0; i < total; i++) {
if (onProgress) {
onProgress({
current: i + 1,
total,
item: args.files[i],
message: `Converting file ${i + 1}/${total}: ${args.files[i]}`
});
}
await processFile(args.files[i]);
}
return { ok: true, result: { count: total } };
}
});You can edit src/state/state.js and src/agent/systemPrompt.js directly, or configure them programmatically:
import { setSystemPromptBuilder } from './agent/systemPrompt.js';
import { setInitialState } from './state/state.js';
// Set a custom initial state model
setInitialState({
servers: [{ id: 'srv-1', name: 'api-gateway', status: 'healthy' }]
});
// Override the dynamic prompt generator
setSystemPromptBuilder((snapshot, dryRun) => {
return `You are a system monitoring agent. Operating in ${dryRun ? 'dry-run' : 'live'} mode.`;
});| Endpoint | Method | Description |
|---|---|---|
/api/state |
GET |
Environment summary, active model, and dry-run flag |
/api/setup |
GET, POST |
Provider credentials and baseURL configuration |
/api/config |
GET, POST |
Runtime model and reasoning effort settings |
/api/models |
GET |
Dynamic model listing from the upstream provider |
/api/snapshot |
GET |
Full JSON state snapshot |
/api/chat |
POST |
Start run or inject mid-flight steering message |
/api/stream/:runId |
GET |
Real-time Server-Sent Events (SSE) stream |
/api/approve |
POST |
Approve or deny a pending destructive tool call |
/api/dry-run |
POST |
Toggle simulation or live armed execution mode |
/api/cancel |
POST |
Cancel active execution run via AbortController |
/api/reset |
POST |
Clear conversation history and active session state |
npm testMIT License. Copyright (c) 2026 walsoup.