Skip to content

Repository files navigation

NanoFleet Agent

TypeScript Bun Docker License

Self-hosted autonomous AI agent runtime — provider-agnostic, channel-independent.

Built with Mastra, Bun + TypeScript.

Lines of code
─────────────────────────────────────────────────────────────────────
Language            Files       Lines    Blanks  Comments       Code
─────────────────────────────────────────────────────────────────────
TypeScript             16       1 706       270        32      1 404
Markdown                9         854       247         0        607
JSON                    6         123         0         0        123
YAML                    3         133        19        15         99
Dockerfile              1          33        13         0         20
License                 1          91        27         0         64
─────────────────────────────────────────────────────────────────────
Total                  36       2 940       576        47      2 317
─────────────────────────────────────────────────────────────────────

Quick Start

cp .env.example .env
# Add your API key (ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or OPENROUTER_API_KEY)
# Set AGENT_MODEL (e.g. claude-haiku-4-5, gemini-2.0-flash, openrouter:meta-llama/llama-3.3-70b-instruct)

# Edit `docker-compose.yml` and uncomment a channel adapter to connect the agent to an external platform.
docker compose up -d

curl http://localhost:4111/health
Development
bun install
bun run dev        # HTTP server with hot reload
bun run lint
bun run format

Workspace

Customize the agent by editing files in workspace/:

File Description
SOUL.md Agent identity — name, worldview, opinions, interests
STYLE.md Communication style guide
MEMORY.md Long-term memory (auto-consolidated after conversations)
HEARTBEAT.md Periodic tasks checklist (runs every 30 min by default)
AGENTS.md Other agents in the system (for multi-agent setups)
cron.json Scheduled jobs (not yet implemented)
skills/ Custom skills — each in its own SKILL.md file

Skills

Skills are Markdown files with YAML frontmatter, placed in workspace/skills/<name>/SKILL.md.

SKILL.md format
---
id: my-skill
name: My Skill
description: Does something useful
requirements:
  binaries: ["jq"]
  env_vars: ["API_KEY"]
---

# Skill instructions here

The agent detects available skills at startup and injects their metadata into the system prompt.

Tools

The agent comes with built-in tools:

Tool Enabled by default Description
Web search Yes Provider-native: Anthropic (webSearch_20250305), Google (googleSearch), OpenRouter (:online suffix)
Web fetch Yes Fetches a URL and returns readable text
File read/write Yes Read and write files in the workspace
Shell No Execute shell commands — enable with SHELL_TOOL_ENABLED=true

Additional tools can be added via MCP servers.

MCP

Add MCP servers in workspace/.mcp.json:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "..." }
    }
  }
}

Tools from MCP servers are automatically discovered and registered at startup.

API

Health & Info

GET /health

curl http://localhost:4111/health
# {"status":"ok"}

GET /identity

curl http://localhost:4111/identity
# {"hasSoul":true,"hasStyle":true,"hasMemory":false,"hasAgents":false}

GET /system-prompt

curl http://localhost:4111/system-prompt

GET /skills

curl http://localhost:4111/skills
# {"skills":[{"id":"...","name":"...","description":"...","available":true}]}
Generate & Stream

POST /api/agents/:id/generate

curl -X POST http://localhost:4111/api/agents/main/generate \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Hello"}]}'

Response:

{
  "text": "Hello! How can I help you?",
  "threadId": "thread-123",
  "usage": { "inputTokens": 100, "outputTokens": 20 },
  "cost": 0.0002
}

Pass threadId in subsequent requests to continue the same conversation. Without it, the last thread is reused automatically.

POST /api/agents/:id/stream

SSE streaming response.

curl -X POST http://localhost:4111/api/agents/main/stream \
  -H "Content-Type: application/json" -N \
  -d '{"messages": [{"role": "user", "content": "Hello"}]}'
Notifications

GET /api/agents/:id/notifications/stream

Subscribe to proactive notifications (SSE). Used by channel adapters to receive messages pushed by the agent (heartbeat results, plugin-triggered alerts, etc.).

curl -N http://localhost:4111/api/agents/main/notifications/stream

Each event is a JSON object:

{ "text": "...", "timestamp": "2026-03-03T07:00:00.000Z", "source": "heartbeat" }

POST /api/agents/:id/notify

Push a notification directly to all connected channels, without invoking the LLM. Intended for plugins that need to deliver content (e.g. a PDF digest) via the channel already connected to the agent.

curl -X POST http://localhost:4111/api/agents/main/notify \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello from a plugin", "source": "my-plugin"}'

To send a document through the channel (e.g. nanofleet-news), pass a JSON payload as text:

{
  "text": "{\"type\":\"document\",\"url\":\"http://nanofleet-plugin-nanofleet-news:8830/digests/2026-03-03.pdf\",\"filename\":\"journal-2026-03-03.pdf\"}",
  "source": "nanofleet-news"
}
Memory

GET /api/agents/:id/memory/threads

curl http://localhost:4111/api/agents/main/memory/threads

POST /api/agents/:id/memory/threads

Create a new thread explicitly (e.g. to start a fresh conversation).

curl -X POST http://localhost:4111/api/agents/main/memory/threads \
  -H "Content-Type: application/json" \
  -d '{"resourceId": "user-123"}'

GET /memory/config

curl http://localhost:4111/memory/config
Usage

GET /api/agents/:id/usage

curl http://localhost:4111/api/agents/main/usage
{
  "totalInputTokens": 10000,
  "totalOutputTokens": 5000,
  "totalCacheReadTokens": 8000,
  "totalCacheWriteTokens": 2000,
  "totalCost": 0.15,
  "cacheHitRate": 80,
  "requests": 50
}

GET /api/agents/:id/usage/threads/:threadId

curl http://localhost:4111/api/agents/main/usage/threads/thread-123

Channels

Channels connect the agent to external platforms (Telegram, Discord, ...). Each channel is a standalone adapter that forwards messages to the agent via HTTP/SSE.

Available channels: nanofleet-agent-channels

The docker-compose.yml includes a commented Telegram example — uncomment and configure it to add a channel alongside the agent.

If you use NanoFleet, channels are deployed and managed from the web dashboard — no manual docker-compose configuration needed.

License

Elastic License 2.0 (ELv2)

About

Another OpenClaw alternative

Topics

Resources

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages