Skip to main content

Lightweight single-file agent framework

Project description

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:

pip install bos-ai

Initialize a workspace:

mkdir my-agent
cd my-agent
bos init

Start the agent runtime:

bos start

Connect the built-in TUI:

bos tui

Useful lifecycle commands:

bos status
bos restart
bos 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:

[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:

[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.

[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:

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

Build and run:

docker build -t bos-ai:local .
bos start
bos 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:

[[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:

[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.

[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:

[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:

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:

  • bos init
  • bos auth
  • bos start
  • bos stop
  • bos status
  • bos restart
  • bos tui

Global workspace selection:

bos -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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bos_ai-1.2.0.tar.gz (260.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bos_ai-1.2.0-py3-none-any.whl (131.7 kB view details)

Uploaded Python 3

File details

Details for the file bos_ai-1.2.0.tar.gz.

File metadata

  • Download URL: bos_ai-1.2.0.tar.gz
  • Upload date:
  • Size: 260.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for bos_ai-1.2.0.tar.gz
Algorithm Hash digest
SHA256 4eb729aeeb996adcc283b35dd0f5c04f506756e4c1b1e57266df8c18503beb7e
MD5 43e634d0bda9a73aad8112ead5c4a6b2
BLAKE2b-256 8de70aaae30909354df26bfff8d10b83ad28ffb3e5627fe151eac9596621f187

See more details on using hashes here.

Provenance

The following attestation bundles were made for bos_ai-1.2.0.tar.gz:

Publisher: release.yml on bos-agent/bos-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bos_ai-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: bos_ai-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 131.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for bos_ai-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f678f6fa750956a262d729f5c439be0ce4529742867ce0f0c086dbbc33781bb5
MD5 ca3eff65bcc176ec499c62598ca903c1
BLAKE2b-256 bffe7fcb5b8b13fde59a444e8d45c07d000e2f742d11e6c6a04e8ca22c6815b9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bos_ai-1.2.0-py3-none-any.whl:

Publisher: release.yml on bos-agent/bos-ai

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page