# Bos

> AI agent framework with multi-language bindings. Agents, tools, bus, MCP, skills — in Rust, Python & JavaScript.

- **Type:** MCP server
- **Install:** `agentstack add mcp-open1s-bos`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [open1s](https://agentstack.voostack.com/s/open1s)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [open1s](https://github.com/open1s)
- **Source:** https://github.com/open1s/bos
- **Website:** https://github.com/open1s/bos/wiki

## Install

```sh
agentstack add mcp-open1s-bos
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

English | [中文版本](./README-ZH.md)

 BrainOS — Multi-language AI agent runtime. One framework — Rust core, Python & JS bindings.

  
  
  
  
  

---

**You have an LLM. You want it to use tools, talk to other agents, remember conversations, and connect to MCP servers — in Python, JavaScript, or Rust.**

BOS is the runtime that makes this work out of the box. One `pip install nbos` or `npm install @open1s/jsbos` gets you agents with tools, a pub/sub event bus for multi-agent coordination, MCP client for external tools, skill loading for domain-specific capabilities, and cross-session memory — all backed by a performant Rust core.

  

```bash
# 30-second win — copy, paste, run
pip install nbos && python -c "
from nbos import BrainOS
import asyncio
print(asyncio.run(BrainOS().agent('assistant').ask('say hi')))
"
```

---

## Quick Start

### Python (brainos)

```python
from nbos import BrainOS, tool
from nbos.content import Content, ContentPart

@tool("Add two numbers")
def add(a: int, b: int) -> int:
    return a + b

async with BrainOS() as brain:
    agent = brain.agent("assistant").with_tools(add)
    result = await agent.ask("What is 2+2?")

    # Multimodal: text + image
    content = Content.parts([
        ContentPart.text("What is in this image?"),
        ContentPart.image("https://example.com/photo.jpg"),
    ])
    result = await agent.ask(content)

    # Multimodal: text + audio
    audio_content = Content.parts([
        ContentPart.text("Transcribe this audio"),
        ContentPart.audio("/path/to/audio.wav", "wav"),
    ])
    result = await agent.ask(audio_content)
```

### JavaScript (@open1s/jsbos / brainos-js)

```javascript
import { BrainOS, ToolDef, Content, ContentPart } from '@open1s/jsbos';

// Create tool using ToolDef
const addTool = new ToolDef(
  'add',
  'Add two numbers',
  (args) => (args.a || 0) + (args.b || 0),
  { type: 'object', properties: { result: { type: 'number' } }, required: ['result'] },
  { type: 'object', properties: { a: { type: 'number' }, b: { type: 'number' } }, required: ['a', 'b'] }
);

const brain = new BrainOS();
await brain.start();
const agent = await brain.agent('assistant')
  .register(addTool)
  .start();
const result = await agent.runSimple('What is 2+2?');

// Multimodal: text + image
const content = Content.parts([
    ContentPart.text('What is in this image?'),
    ContentPart.image('https://example.com/photo.jpg'),
]);
const result2 = await agent.ask(content);

// Multimodal: text + audio
const audioContent = Content.parts([
    ContentPart.text('Transcribe this audio'),
    ContentPart.audio('/path/to/audio.wav', 'wav'),
]);
const result3 = await agent.ask(audioContent);
```

### Rust (agent crate)

```rust
use agent::{Agent, AgentConfig};

let config = AgentConfig::default().name("assistant");
let agent = Agent::builder().config(config).build()?;
let result = agent.run_simple("Hello").await?;
```

---

## Why BOS?

BOS is not another LangChain wrapper or Python-only framework. It's a **multi-language runtime** built from the ground up for production AI agents.

| Need | BOS | Typical alternative |
|------|-----|-------------------|
| **Language choice** | Rust core + Python `nbos` + JavaScript `@open1s/jsbos` | Python-only |
| **Multi-agent** | Built-in event bus (pub/sub, query/RPC, caller/callable) | Ad-hoc or single-process |
| **External tools** | Native MCP client (stdio + HTTP) | Roll your own |
| **Agent capabilities** | Directory-based skills system — load domain expertise on demand | Hardcoded prompts |
| **Memory** | Cross-session persistence built in | Plugin or DIY |
| **Production** | Circuit breaker, rate limiter, configurable resilience | Often absent |
| **Performance** | Rust zero-cost abstractions, async Tokio runtime | GIL-bound Python |

**If you want an agent that speaks more than one language, talks to other agents, and works in production — not just a notebook — BOS is the runtime.**

---

## Skills System

Agents can load capabilities from directory-based skill definitions:

```python
# Create skills directory with skill folders
skills_dir = "/path/to/skills"
agent.register_skills_from_dir(skills_dir)
```

### Skill Format

Each skill is a directory containing a `SKILL.md` file with YAML frontmatter:

```
skills/
├── python-coding/
│   └── SKILL.md
├── api-design/
│   └── SKILL.md
└── database-ops/
    └── SKILL.md
```

**SKILL.md format:**
```markdown
---
name: python-coding
description: Python coding conventions for this project
category: coding
version: 1.0.0
---

# Python Coding Conventions

Your skill instructions here...
```

The agent's LLM receives available skills in the system prompt and can call `load_skill` to retrieve full instructions.

---

## Project Structure

```
bos/
├── crates/
│   ├── agent/          # AI agent framework with LLM, skills, tools, MCP
│   ├── bus/            # Pub/sub, queryable, caller/callable
│   ├── config/         # TOML/YAML config loading
│   ├── logging/        # Tracing and instrumentation
│   ├── react/          # ReAct reasoning engine
│   ├── nbos/           # Python bindings (nbos package)
│   └── jsbos/          # Node.js bindings (@open1s/jsbos)
├── docs/               # User guides
│   ├── python-user-guide.md
│   ├── javascript-user-guide.md
│   └── rust-user-guide.md
└── Cargo.toml          # Workspace
```

---

## Crates

| Crate | Description | Install |
|-------|-------------|---------|
| `agent` | Core agent with LLM integration, tools, skills, MCP | `cargo add agent` |
| `bus` | Pub/sub, query/response, RPC messaging | `cargo add bus` |
| `config` | Config loading from TOML, YAML, env vars | `cargo add config` |
| `logging` | Tracing and observability | `cargo add logging` |
| `react` | ReAct reasoning + acting engine | `cargo add react` |
| `nbos` | Python bindings | `pip install nbos` |
| `jsbos` | Node.js bindings | `npm install @open1s/jsbos` |

---

## Commands

```bash
# Build all
cargo build --all

# Test all
cargo test --all

# Lint
cargo clippy --all
cargo fmt --all

# Python bindings (nbos)
cd crates/nbos && maturin develop

# Node.js bindings (jsbos)
cd crates/jsbos && npm install && npm run build
```

---

## User Guides

- **Python**: [docs/python-user-guide.md](docs/python-user-guide.md)
- **JavaScript**: [docs/javascript-user-guide.md](docs/javascript-user-guide.md)
- **Rust**: [docs/rust-user-guide.md](docs/rust-user-guide.md)
- **中文**: [README-ZH.md](README-ZH.md)

---

## Unified API

The `nbos` package (Python) and `@open1s/jsbos` (JavaScript) provide consistent high-level APIs:

| Feature | Python | JavaScript |
|---------|--------|------------|
| Import | `from nbos import BrainOS, tool` | `import { BrainOS, ToolDef } from '@open1s/jsbos'` |
| Create brain | `async with BrainOS() as brain:` | `const brain = new BrainOS(); await brain.start()` |
| Create agent | `brain.agent("name")` | `brain.agent("name")` |
| Fluent config | `.with_model("gpt-4")` | `.model("gpt-4")` |
| Register tools | `.with_tools(tool)` | `.register(toolDef)` |
| Run | `await agent.ask("...")` | `await agent.runSimple("...")` |
| Text content | `Content.text("...")` | `Content.text("...")` |
| Image content | `ContentPart.image(url)` | `ContentPart.image(url)` |
| Audio content | `ContentPart.audio(data, format)` | `ContentPart.audio(data, format)` |
| Bus factory | `BusManager()` | `BusManager.create()` |

### Low-level Bindings

For direct access to Rust bindings:

| Language | Package | Import |
|----------|---------|--------|
| Python | `nbos` | `from nbos import Agent, Bus, McpClient, ...` |
| JavaScript | `@open1s/jsbos` | `import { Agent, Bus, McpClient } from '@open1s/jsbos'` |

---

## MCP Client

Connect to MCP servers via stdio or HTTP transport:

### Python

```python
from nbos import McpClient

# Process-based server
client = await McpClient.spawn("npx", ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"])
await client.initialize()

# HTTP server
client = McpClient.connect_http("http://127.0.0.1:8000/mcp")
await client.initialize()

# Use tools
tools = await client.list_tools()
result = await client.call_tool("echo", '{"text": "hello"}')
```

### JavaScript

```javascript
import { McpClient } from '@open1s/jsbos';

// Process-based server
const client = await McpClient.spawn("npx", ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]);
await client.initialize();

// HTTP server
const client = McpClient.connectHttp("http://127.0.0.1:8000/mcp");
await client.initialize();

// Use tools
const tools = await client.listTools();
const result = await client.callTool("echo", '{"text": "hello"}');
```

### HTTP Server Example

```bash
# Start an MCP HTTP server
python3 crates/examples/mcp_http_server.py
# Server runs on http://127.0.0.1:8000/mcp
```

---

## Configuration

Create `~/.bos/conf/config.toml`:

```toml
# OpenAI-compatible endpoint
[global_model]
api_key = "your-api-key"
base_url = "https://api.openai.com/v1"
model = "gpt-4"

# NVIDIA NIM
[llm.nvidia]
api_key = "nv-..."
base_url = "https://integrate.api.nvidia.com/v1"
model = "nvidia/llama-3.1-nemotron-70b-instruct"

# Google AI (Gemini, etc.)
[llm.google]
api_key = "google-api-key"
base_url = "https://generativelanguage.googleapis.com/v1"
model = "gemini-pro"

# OpenRouter
[llm.openrouter]
api_key = "or-..."
base_url = "https://openrouter.ai/api/v1"
model = "anthropic/claude-3-haiku"

[bus]
mode = "peer"
listen = ["127.0.0.1:7890"]
```

Or use environment variables: `OPENAI_API_KEY`, `LLM_BASE_URL`, `LLM_MODEL`

---

## Examples

See the examples directories:

- Python: `crates/nbos/examples/`
- JavaScript: `crates/jsbos/examples/`
- Rust: `crates/examples/` (includes `agent_skill_demo.rs`)

### Multimodal Demos

```bash
# Python multimodal (text, image, audio)
python crates/nbos/examples/demo_multimodal.py

# JavaScript multimodal (text, image, audio)
node crates/jsbos/examples/demo_multimodal.js

# JavaScript audio demo
node crates/jsbos/examples/demo_audio.js
```

### MCP Demos

```bash
# JavaScript MCP HTTP demo
node crates/jsbos/examples/mcp_http_agent_demo.js

# Python MCP HTTP demo (run server first, then use)
python3 crates/examples/mcp_http_server.py
```

---

## License

MIT OR Apache-2.0

---

## Changelog

### v2.3.6 (2026-07-01)

- **Added**: `skill_dir` to `load_skill` tool result — LLM receives the parent path of `SKILL.md` for accessing bundled resources

### v2.3.5

- **Added**: Skills system: directory-based skill loading with `SKILL.md` files
- **Added**: `load_skill` tool — LLM can load skill instructions on demand
- **Added**: Skill caching with TTL in ReAct engine
- **Fixed**: Skill load performance — avoid redundant filesystem reads

### v2.3.0 (2026-06-09)

- **Added**: Audio support — `Content.audio()`, `ContentPart.audio()` for multimodal LLM calls
- **Added**: LLM vendor configuration — `[llm.google]`, `[llm.nvidia]`, `[llm.openrouter]` in config
- **Added**: `demo_audio.js` and `demo_multimodal.js` examples
- **Added**: `demo_multimodal.py` Python example
- **Improved**: Content API — unified `Content`/`ContentPart`/`Binary` classes for text, images, audio
- **Fixed**: Content serialization for multimodal messages

### v2.2.0 (2026-05-18)

- **Added**: `agent.stop()` — stop a running agent/react/stream via ESC key
- **Added**: `agent.is_running()` — check if agent is currently running
- **Added**: Stop flag and running state in NAPI Agent layer
- **Added**: `StreamToken::Stopped` variant for stream cancellation
- **Added**: Concurrent call prevention with error "Agent is already running"
- **Added**: Stream returns `{status: "stopped"|"completed"}` JSON string
- **Breaking**: `stream()` now returns `String` (JSON status object) instead of `()`

### v2.1.4 (2026-05-15)

- **Fixed**: `getPerfMetrics()` now correctly updates after `stream()` calls
- **Added**: Token usage tracking — `totalInputTokens` and `totalOutputTokens` are now recorded from LLM responses for `react()`, `runSimple()`, and `stream()`
- **Added**: Tool invocation tracking — `toolInvocationCount` records actual tool calls made by the agent
- **Renamed**: Metrics fields for clarity: `callCount` → `llmCallCount`, `toolCallCount` → `toolInvocationCount`
- **Added**: `agent_metrics_demo.js` example to verify metrics recording

### v2.1.3 (2026-05-13)

- Previous release

---

**Version**: 2.3.6 | **Last Updated**: 2026-07-01

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [open1s](https://github.com/open1s)
- **Source:** [open1s/bos](https://github.com/open1s/bos)
- **License:** MIT
- **Homepage:** https://github.com/open1s/bos/wiki

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-open1s-bos
- Seller: https://agentstack.voostack.com/s/open1s
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
