Skip to content

Quickstart

Terminal window
bun add zupdev

Create an agent with no plugins and run a single loop:

import { createAgent } from 'zupdev';
const agent = await createAgent({ name: 'my-agent' });
const result = await agent.runLoop();
console.log('Loop completed in', result.duration, 'ms');
console.log('Observations:', result.observations.length);

Without plugins there are no observers, so the loop completes instantly with zero observations. The next sections add real capabilities.

Install the http-monitor plugin to watch your endpoints:

import { createAgent } from 'zupdev';
import { httpMonitor } from 'zupdev/plugins/http-monitor';
const agent = await createAgent({
name: 'my-agent',
plugins: [
httpMonitor({
endpoints: [
{ id: 'api', name: 'API', url: 'https://api.example.com/health' },
{ id: 'web', name: 'Website', url: 'https://example.com' },
],
}),
],
});
const result = await agent.runLoop();
console.log('Situation:', result.situation?.summary);

The http-monitor plugin registers an observer, an orienter, a decision strategy, and a restart action. A single runLoop() call runs through all four OODA phases.

Plugins like the investigation-orienter and historian require an LLM for deeper analysis. Configure one under the llm key:

const agent = await createAgent({
name: 'my-agent',
llm: {
provider: 'anthropic',
apiKey: process.env.ANTHROPIC_API_KEY!,
model: 'claude-sonnet-4-6',
},
plugins: [
httpMonitor({
endpoints: [
{ id: 'api', name: 'API', url: 'https://api.example.com/health' },
],
}),
],
});

Zup supports 16+ providers. For example, OpenAI:

llm: {
provider: 'openai',
apiKey: process.env.OPENAI_API_KEY!,
model: 'gpt-4o',
}

See LLM Providers for Google Gemini, Mistral, Groq, xAI, OpenRouter, Azure, Bedrock, Vertex AI, and others.

The historian plugin stores incident history in SQLite and uses it for RAG during future loops:

import { createAgent } from 'zupdev';
import { httpMonitor } from 'zupdev/plugins/http-monitor';
import { historianPlugin } from 'zupdev/plugins/historian';
const agent = await createAgent({
name: 'my-agent',
llm: {
provider: 'anthropic',
apiKey: process.env.ANTHROPIC_API_KEY!,
model: 'claude-sonnet-4-6',
},
sqlite: { path: './zup.db' },
plugins: [
httpMonitor({
endpoints: [
{ id: 'api', name: 'API', url: 'https://api.example.com/health' },
],
}),
historianPlugin({ minConfidence: 0.75 }),
],
});

Expose an HTTP API so external systems can trigger loops, submit runs, and approve actions:

const agent = await createAgent({
name: 'my-agent',
plugins: [
httpMonitor({
endpoints: [
{ id: 'api', name: 'API', url: 'https://api.example.com/health' },
],
}),
],
});
const server = agent.startApi({
port: 3000,
apiKeys: ['my-secret-key'],
});
console.log(`API running on port ${server.port}`);

Test it:

Terminal window
# Health check (no auth)
curl http://localhost:3000/api/v0/health
# Trigger a loop
curl -X POST http://localhost:3000/api/v0/loop/trigger \
-H "Authorization: Bearer my-secret-key"
# Submit a run
curl -X POST http://localhost:3000/api/v0/runs \
-H "Authorization: Bearer my-secret-key" \
-H "Content-Type: application/json" \
-d '{"title": "Check API latency", "description": "Users report slow responses"}'

Set mode: 'continuous' and loopInterval when creating the agent. Then call start() with no arguments:

const agent = await createAgent({
name: 'my-agent',
mode: 'continuous',
loopInterval: 30000, // 30 seconds
plugins: [
httpMonitor({
endpoints: [
{ id: 'api', name: 'API', url: 'https://api.example.com/health' },
],
}),
],
});
// start() reads mode and loopInterval from the agent config
const stop = await agent.start();
// Later, stop the loop:
// stop();