https://github.com/moikapy/nimbus-mono
0xNIMBUS — Cloudflare-native AI agent with local-first runtime
https://github.com/moikapy/nimbus-mono
Last synced: 2 months ago
JSON representation
0xNIMBUS — Cloudflare-native AI agent with local-first runtime
- Host: GitHub
- URL: https://github.com/moikapy/nimbus-mono
- Owner: Moikapy
- Created: 2026-04-21T04:29:14.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2026-04-21T06:18:16.000Z (2 months ago)
- Last Synced: 2026-04-21T08:28:29.149Z (2 months ago)
- Language: JavaScript
- Size: 810 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Nimbus ☁️⚡
> *The golden cloud that only the pure of heart can ride.*
Nimbus is the **Cloudflare agent harness** — everything except the model. Built on the Agents SDK, wired through AI Gateway, fast as Kintoun.
## What is Nimbus?
An **agent harness** is the complete architectural system surrounding an LLM that manages the lifecycle of context: from intent capture through tool execution, verification, and persistence. Nimbus handles everything except the model itself — tools, memory, context, verification, and state.
You extend `NimbusChatAgent`, add plugins for your domain with `.use(plugin)`, and deploy. No building agent loops from scratch. No vendor lock-in.
```typescript
import { NimbusChatAgent } from "nimbus-agent";
import { treasuryPlugin } from "nimbus-treasury";
export class FederalDataAgent extends NimbusChatAgent {
constructor(ctx, env) {
super(ctx, env);
this.use(treasuryPlugin);
}
}
```
That's it. One harness. Add plugins. Ship.
## Why "Nimbus"?
Goku's Flying Nimbus (筋斗雲, Kintoun) is a magical golden cloud. It's fast, it goes anywhere, and **only the pure of heart can ride it**. That's the philosophy:
- **Pure of heart** — Nimbus refuses harmful requests. Guard rails aren't optional, they're identity.
- **Rides the cloud** — Born on Cloudflare's Agents SDK. Per-instance SQLite, WebSocket streaming, hibernation safety.
- **Goes anywhere** — Workers AI, AI Gateway, OpenAI, Anthropic — one interface, any model.
- **One harness, many riders** — The harness is the cloud. Plugins are the passengers.
## Architecture
```
NimbusChatAgent (the harness ☁️)
├── extends AIChatAgent (Agents SDK)
│ ├── Per-instance SQLite (this.sql)
│ ├── Message persistence (this.messages)
│ ├── WebSocket streaming (resumable)
│ ├── Hibernation safety (state survives eviction)
│ └── useAgentChat (React hook)
├── .use(plugin) (the composition layer)
│ ├── Plugin tools → AI SDK tool() format
│ ├── Plugin instructions → system prompt merge
│ └── Plugin MCP servers → tool discovery
├── Tool execution (Zod validation + error feedback)
├── Model providers (which wind you ride)
│ ├── Workers AI (default — Cloudflare native)
│ └── AI Gateway (unified — any provider)
└── Presets (pre-built tools)
├── httpTools ← domain-allowlisted fetch
└── dataTools ← filter, sort, aggregate
```
## Quick Start
### Install
```bash
bun add nimbus-agent
```
### Create an Agent
```typescript
import { NimbusChatAgent } from "nimbus-agent";
import { treasuryPlugin } from "nimbus-treasury";
// Extend the harness, add plugins
export class MyAgent extends NimbusChatAgent {
constructor(ctx, env) {
super(ctx, env);
this.use(treasuryPlugin);
}
}
```
### Add a Custom Plugin
```typescript
// A plugin is just { name, tools, instructions }
const myPlugin = {
name: "my-tools",
description: "Custom tools for my app",
instructions: "When answering questions about X, always cite the source.",
tools: {
lookup_data: {
description: "Look up data from my API",
parameters: z.object({ query: z.string() }),
execute: async (params, ctx) => fetch(`/api/data?q=${params.query}`).then(r => r.json()),
},
},
};
// Use it
this.use(myPlugin);
```
### Deploy
```typescript
// src/worker.ts
import { NimbusChatAgent } from "nimbus-agent";
import { routeAgentRequest } from "agents";
export class MyAgent extends NimbusChatAgent {
constructor(ctx, env) { super(ctx, env); this.use(treasuryPlugin); }
}
export default {
async fetch(request, env) {
return routeAgentRequest(request, env) || new Response("Not found", { status: 404 });
},
};
```
console.log(result.data); // Raw data from tools
console.log(result.steps); // How many tool-call iterations
console.log(result.tokens); // Token usage
console.log(result.duration); // Time in ms
```
## Model Providers
### Workers AI (default)
Uses the `env.AI` binding in Cloudflare Workers. No API key needed.
```typescript
createNimbus({
model: "workers-ai:@cf/zai-org/glm-4.7-flash",
});
```
### AI Gateway (unified)
Route any provider through Cloudflare AI Gateway. BYOK — bring your own keys, stored in the gateway.
```typescript
createNimbus({
model: "unified:openai/gpt-5.2",
gateway: {
accountId: "your-account-id",
gateway: "your-gateway-id",
apiKey: "your-gateway-key",
},
});
```
### Fallback Chain
Try the primary model, fall back if it fails:
```typescript
createNimbus({
model: "unified:anthropic/claude-4-5-sonnet",
fallbacks: ["workers-ai:@cf/zai-org/glm-4.7-flash"],
});
```
## Memory
### In-Memory (dev/test)
```typescript
import { inMemory } from "nimbus-agent/memory";
createNimbus({
model: "workers-ai:...",
memory: inMemory(),
});
```
### D1 (production)
```typescript
import { d1Memory } from "nimbus-agent/memory";
createNimbus({
model: "workers-ai:...",
memory: d1Memory(env.DB),
});
```
### KV (edge cache)
```typescript
import { kvMemory } from "nimbus-agent/memory";
createNimbus({
model: "workers-ai:...",
memory: kvMemory(env.CACHE),
});
```
## Preset Tools
### HTTP Tools
```typescript
import { httpTools } from "nimbus-agent/presets";
const nimbus = createNimbus({
model: "workers-ai:...",
}).use({
name: "http",
tools: httpTools({ allowedDomains: ["api.example.com"] }),
});
```
### Data Tools
Filter, sort, aggregate, top-N tools for data the model already has:
```typescript
import { dataTools } from "nimbus-agent/presets";
// Adds data_filter, data_sort, data_aggregate, data_top
```
## Plugin API
A plugin adds tools, instructions, and/or MCP servers to the agent:
```typescript
interface NimbusPlugin {
name: string;
description?: string;
tools?: Record;
mcpServers?: McpServerConfig[];
instructions?: string; // Added to the system prompt when this plugin is active
}
```
Chain them:
```typescript
const nimbus = createNimbus({ model, instructions })
.use(treasuryPlugin) // federal data tools
.use(searchPlugin) // web search
.use(weatherPlugin); // weather data
console.log(nimbus.plugins());
// ["nimbus-treasury", "nimbus-search", "nimbus-weather"]
```
Each plugin's instructions are appended to the system prompt under a `--- plugin-name ---` header. Tools merge. MCP servers accumulate. No conflicts, no overwrites.
## The Pure of Heart Clause
Nimbus refuses to:
- **Harm people** — no weapons, no surveillance, no exploitation
- **Deceive or manipulate** — no disinformation, no social engineering
- **Violate privacy** — no unauthorized data collection, no stalking
- **Build systems for evil** — even if profitable
This isn't a feature. It's identity. The Flying Nimbus only carries the pure of heart. If you can't ride it, the problem isn't the cloud.
## Deploying on Cloudflare
### Wrangler Setup
```jsonc
// wrangler.jsonc
{
"ai": { "binding": "AI" },
"d1_databases": [{ "binding": "DB", "database_name": "nimbus-db" }],
"kv_namespaces": [{ "binding": "CACHE", "id": "your-kv-id" }]
}
```
### Worker Entry
```typescript
import { createNimbus } from "nimbus-agent";
export default {
async fetch(request: Request, env: Record) {
const nimbus = createNimbus({
model: "workers-ai:@cf/zai-org/glm-4.7-flash",
memory: d1Memory(env.DB as D1Database),
}).use(myPlugin);
const { searchParams } = new URL(request.url);
const question = searchParams.get("q") ?? "Hello";
const result = await nimbus.run(question, { env });
return Response.json(result);
},
};
```
## API Reference
### `createNimbus(config)`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `model` | `string` | *required* | Model reference (e.g. `workers-ai:@cf/...` or `unified:provider/model`) |
| `instructions` | `string` | `""` | System prompt |
| `tools` | `Record` | `{}` | Inline tool definitions |
| `mcpServers` | `McpServerConfig[]` | `[]` | Remote MCP tool servers |
| `fallbacks` | `string[]` | `[]` | Fallback model references |
| `memory` | `MemoryStore` | `null` | Conversation memory store |
| `tracing` | `TraceStore` | `null` | Trace storage |
| `context` | `object` | `{history:10, memory:true, maxContextTokens:8000, compaction:"summarize"}` | Context window config |
| `maxSteps` | `number` | `10` | Max tool-call iterations |
| `maxTokens` | `number` | `4096` | Max output tokens |
| `timeout` | `number` | `30000` | Request timeout (ms) |
| `retries` | `number` | `1` | Model call retries |
| `retryDelay` | `number` | `1000` | Retry delay (ms) |
### `nimbus.run(question, options?)`
Returns `Promise`:
| Field | Type | Description |
|-------|------|-------------|
| `answer` | `string` | The agent's final response |
| `data` | `unknown[]` | Raw data collected from tool calls |
| `sources` | `NimbusSource[]` | Which tools were used and what they returned |
| `trace` | `NimbusTrace[]` | Full execution trace for debugging |
| `model` | `string` | Which model was used |
| `steps` | `number` | Tool-call iterations executed |
| `tokens` | `{input, output, total}` | Token usage estimate |
| `duration` | `number` | Total execution time (ms) |
### `nimbus.use(plugin)`
Add a plugin. Returns `Nimbus` for chaining.
### `nimbus.plugins()`
List active plugin names.
## License
MIT
---
*Born on the cloud. Pure of heart. Fast as Kintoun.* ☁️⚡