Metadata-Version: 2.4
Name: bos-ai
Version: 1.3.0
Summary: Lightweight single-file agent framework
Project-URL: Homepage, https://github.com/bos-agent/bos-ai
License: BSD 2-Clause License
        
        Copyright (c) 2024-2026, bos-ai contributors
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions are met:
        
        1. Redistributions of source code must retain the above copyright notice, this
           list of conditions and the following disclaimer.
        
        2. Redistributions in binary form must reproduce the above copyright notice,
           this list of conditions and the following disclaimer in the documentation
           and/or other materials provided with the distribution.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License-File: LICENSE
Requires-Python: >=3.13
Requires-Dist: aiohttp>=3.13.5
Requires-Dist: beautifulsoup4>=4.14.3
Requires-Dist: click>=8.1.7
Requires-Dist: filelock>=3.19.1
Requires-Dist: litellm==1.83.0
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: rich>=13.0.0
Requires-Dist: textual-autocomplete>=4.0.6
Requires-Dist: textual>=1.0.0
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
Provides-Extra: all
Requires-Dist: oauth-cli-kit>=0.1.3; extra == 'all'
Requires-Dist: tavily-python>=0.7.23; extra == 'all'
Provides-Extra: providers
Requires-Dist: oauth-cli-kit>=0.1.3; extra == 'providers'
Provides-Extra: search
Requires-Dist: tavily-python>=0.7.23; extra == 'search'
Description-Content-Type: text/markdown

# BOS AI

Lightweight, extensible infrastructure for building agentic systems in Python.

`bos-ai` is an actor-based framework for running LLM-driven agents with explicit
message routing, configurable runtime boundaries, and a small core. It is meant
to be shaped into different kinds of agentic systems rather than forcing one
opinionated product workflow.

## What It Is

- Fully configurable: agents, tools, skills, memories, channels, runtime, and
  storage are configured in TOML and wired through extension points.
- Actor-based: agents communicate through a `MailRoute` plus bound `MailBox`
  capabilities instead of direct in-process coupling.
- Built for composition: the same core can back a local TUI, an HTTP/WebSocket
  endpoint, or a Telegram bot. Server-side chat cursors let one client
  resume threads created from another client.
- Small core, explicit boundaries: contracts, defaults, harness lifecycle,
  runtime orchestration, and extensions are kept separate.

## Privacy

BOS AI does not ship with built-in telemetry, analytics, or hosted data
collection. Your privacy boundary is defined by the models, tools, channels, and
storage backends you configure.

If you use your own local or self-hosted model and keep your channels and
storage local, BOS AI itself does not require sending your data to any BOS-owned
service.

## Quickstart

Install the package:

```bash
pip install bos-ai
```

Initialize a workspace:

```bash
mkdir my-agent
cd my-agent
boscli init
```

Start the agent runtime:

```bash
boscli gateway start
```

Connect the built-in TUI:

```bash
boscli tui
```

Useful lifecycle commands:

```bash
boscli gateway status
boscli gateway restart
boscli gateway stop
```

## Workspace Model

Each workspace gets a `.bos/config.toml`. BOS AI searches upward from the
current directory for `.bos/config.toml`. If no workspace-local `.bos` exists,
set `BOS_DIR` explicitly. If both an ancestor `.bos` and `BOS_DIR` are present
but point to different locations, BOS AI fails with an ambiguity error instead
of silently choosing one.

Agent definitions may stay inline in `.bos/config.toml` or be placed in external
directories. By default, `.bos/agents/` is auto-scanned. To customize the scan
locations:

```toml
[platform]
agent_dirs = ["agents", "../shared-agents", "~/.bos/agents", "/opt/agents"]
```

Relative paths are resolved against `.bos/`; absolute paths and `~` are
supported. External agents are `<dir>/<name>.toml` files or `<dir>/<name>.md`
files. For Markdown agents, optional YAML-style frontmatter supplies settings
such as `name`, `description`, `tools`, and `exclude_tools`; the Markdown body is
the `system_prompt`. If `name` is provided in the file it is used as-is; if
omitted, the name is derived from the filename stem. Inline agents load first,
external agents load second (alphabetically within each directory, directories
processed in list order), exact-name duplicates are last-wins, and case-only
collisions are errors. `Workspace.config` stays as the raw manifest, and
runtime-facing agent config is produced through a resolved platform view.

For the full rule set and resolver behavior, see
`docs/architecture/config-workspace.md`.

By default, the primary actor is addressed as `agent@main`. The selected main
agent implementation is configured separately under `[main].agent`.

Example channel configuration:

```toml
[main]
agent = "main"

[[main.channels]]
name = "HttpChannel"
bind_address = "channel@http"
target_address = "agent@main"
host = "127.0.0.1"
port = 5920

#[[main.channels]]
#name = "TelegramChannel"
#bind_address = "channel@telegram"
#target_address = "agent@main"
#token = "123456:telegram-bot-token"
#poll_timeout = 30
#allowed_chat_ids = [123456789]
```

This keeps routing explicit:

- channels target `agent@main` directly
- client cursors are stored server-side by `client_id`
- aliases can point to durable `chat_id` values for cross-client resume

### Named Actors

Named Actors let one runtime host multiple long-lived, addressable actors. The
actor key under `[main.actors]` is the route name, mailbox identity, and memory
scope. The `agent` field is the reusable agent kind, so multiple actors can
instantiate the same agent definition with different runtime identities.

```toml
[main.actors.main]
agent = "assistant"
display_name = "Main"

[main.actors.bob]
agent = "architect"
display_name = "Bob"

[main.actors.investment]
agent = "assistant"
display_name = "Investment"
```

Channels that support mention routing can route a message such as `@bob review
this design` to `agent@bob`. Channels can also bind directly to a specific actor
with `target_address = "agent@investment"`.

Named Actors is a routing feature, not autonomous swarm orchestration. Planning,
delegation lifecycle, actor-to-actor relay, and result synthesis belong in a
separate orchestration layer.

## Runtime

The agent can run in-process or in Docker.

Docker runtime example:

```toml
[main.runtime]
kind = "docker"
image = "bos-ai:local"
workspace_dir = "/workspace"
```

Build and run:

```bash
docker build -t bos-ai:local .
boscli gateway start
boscli tui
```

When Docker is enabled, `HttpChannel` host binding is normalized for container
access, and BOS AI publishes configured HTTP channel ports automatically.

Named agents are capability-deny by default. Omitted `tools`, `skills`,
`memories`, and `subagents` settings are treated as empty allow-lists. Configure
each agent with explicit allow-lists, or use `"*"` to allow all names in that
capability group:

```toml
[[platform.agents]]
name = "main"
tools = ["ReadFile", "SearchFiles"]
skills = "*"
memories = ["user", "memory"]
subagents = ["researcher"]
```

`exclude_tools`, `exclude_skills`, `exclude_memories`, and `exclude_subagents`
can still be used to subtract names from an allow-list, including from `"*"`.
Scratch agents created directly through `harness.create_agent()` without a named
agent config also start with no tools, skills, memories, or subagents.

## Skills

Skills are discovered from configured skill directories. A skill is a directory
containing `SKILL.md`; the directory name is the skill name. Configure workspace
skill roots with:

```toml
[harness.skills_loader]
skill_dirs = ["skills"]
```

Agents see allowed skills in the system prompt with each skill's `SKILL.md`
location and summary. `LoadSkill` reads and returns the full `SKILL.md`
instructions as a tool result; it does not permanently mutate the agent's
system prompt.

## Subagent Orchestration

BOS already supports a lightweight form of subagent orchestration inside one
active harness. The pattern is:

- register multiple named agent profiles under `platform.agents`
- allow the parent agent to use the local `AskSubagent` tool
- scope which specialists it may call with `subagents = [...]`
- customize specialist behavior under `[[harness.subagents]]`

This is delegated orchestration, not a second long-running actor process. The
parent agent stays at `agent@main`, while specialist agents are invoked on
demand as additional `agent.ask(...)` calls with their own chat IDs.

Minimal use case: a manager agent handles the user-facing chat and
delegates focused document analysis to a `researcher` subagent.

```toml
[platform.agent_defaults]
tools = []
subagents = []

[[platform.agents]]
name = "main"
description = "User-facing manager."
tools = ["AskSubagent"]
subagents = ["researcher"]
system_prompt = """
Handle the user-facing workflow. Delegate focused repo analysis when needed.
"""

[[platform.agents]]
name = "researcher"
description = "Focused repo analyst."
tools = []
system_prompt = """
You only perform focused research tasks delegated by the main agent.
Return concise findings.
"""

[[harness.subagents]]
name = "researcher"
task_template = """
You are the {agent_name} specialist.
Use this dedicated thread for delegated analysis work.

Task:
{task}
"""
```

`AskSubagent` always runs the specialist in a fresh child thread. The runtime
derives that child `chat_id` from the current parent thread plus a
short agent tag and random suffix, for example
`parent-chat~researcher1a2b3c4d`.

## Extension Points

The framework is designed to be reconfigured and extended, not forked.

## Harness Consolidator

Chat history compaction is handled by a harness-level consolidator service. The
agent owns the dynamic history budget (`max_tokens`) and decides when compaction
is needed; the consolidator owns the model and instruction used to summarize.

Configure the default LLM-backed consolidator with:

```toml
[harness.consolidator]
model = "gemini/gemini-2.5-flash"
instruction = """
Summarize the conversation history for future turns.
Preserve user intent, decisions, unresolved tasks, tool results, and important constraints.
"""
```

The consolidator model is resolved from `harness.consolidator.model`, then
`BOS_CONSOLIDATOR_MODEL`, then `BOS_MODEL`. It does not fall back to
`platform.agent_defaults.model`.

Core extension points include:

- `@ep_provider` for model backends
- `@ep_tool` for tool calls
- `@ep_memory_store` for long-term memory backends
- `@ep_message_store` for chat history
- `@ep_mail_route` for message transport
- `@ep_turn_interceptor` for turn loop interception
- `@ep_channel` for external interfaces like HTTP, Telegram, or grouped channels

Minimal example:

```python
from bos.core import ep_tool


@ep_tool(
    name="echo_upper",
    description="Return an uppercase version of the input.",
    parameters={
        "type": "object",
        "properties": {"text": {"type": "string"}},
        "required": ["text"],
    },
)
async def echo_upper(text: str) -> str:
    return text.upper()
```

Load extensions by adding their modules to `platform.extensions` in
`.bos/config.toml`.

## CLI

The built-in CLI currently exposes:

- `boscli init`
- `boscli auth`
- `boscli gateway start`
- `boscli gateway stop`
- `boscli gateway status`
- `boscli gateway restart`
- `boscli tui`

Global workspace selection:

```bash
boscli -w /path/to/workspace start
```

## What BOS AI Is Good For

- local-first agent runtimes
- custom tool-using assistants
- multi-agent or actor-based orchestration experiments
- private deployments with self-hosted models
- channel-driven agents exposed over HTTP or Telegram

If you want a fixed hosted product, this repo is probably too low-level. If you
want infrastructure for shaping your own agent runtime, this is the right layer.
