Metadata-Version: 2.4
Name: albusos
Version: 0.11.2
Summary: AlbusOS - AI agent runtime with pathway-based execution and composable skills
Keywords: ai,agent,llm,pathway,orchestration,skills
Author: Albus Studio
License-Expression: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Dist: pydantic>=2.0,<3
Requires-Dist: pydantic-graph>=1.47.0
Requires-Dist: aiohttp>=3.9,<4
Requires-Dist: ddgs>=9.0,<10
Requires-Dist: idna>=3.6,<4
Requires-Dist: openai>=1.0,<2
Requires-Dist: httpx>=0.27.0,<0.28
Requires-Dist: anthropic>=0.20,<0.21
Requires-Dist: python-dotenv>=1.0,<2
Requires-Dist: aiostream>=0.6.4,<0.7
Requires-Dist: pyyaml>=6.0.3,<7
Requires-Dist: mcp>=1.0,<2
Requires-Dist: rich>=14.3.2
Requires-Dist: pysbd>=0.3.4
Requires-Dist: fasta2a>=0.6.0 ; extra == 'a2a'
Requires-Dist: starlette>=0.38.0 ; extra == 'a2a'
Requires-Dist: uvicorn>=0.30.0 ; extra == 'a2a'
Requires-Dist: google-generativeai>=0.5,<0.6 ; extra == 'all'
Requires-Dist: fasta2a>=0.6.0 ; extra == 'all'
Requires-Dist: starlette>=0.38.0 ; extra == 'all'
Requires-Dist: uvicorn>=0.30.0 ; extra == 'all'
Requires-Dist: pypdf>=6.6.2 ; extra == 'all'
Requires-Dist: pdfplumber>=0.11.9 ; extra == 'all'
Requires-Dist: pymupdf>=1.26.7 ; extra == 'all'
Requires-Dist: python-docx>=1.2.0 ; extra == 'all'
Requires-Dist: openpyxl>=3.1.5 ; extra == 'all'
Requires-Dist: duckdb>=1.4.4 ; extra == 'all'
Requires-Dist: polars>=1.38.0 ; extra == 'all'
Requires-Dist: pyarrow>=23.0.0 ; extra == 'all'
Requires-Dist: charset-normalizer>=3.4.4 ; extra == 'all'
Requires-Dist: ftfy>=6.3.1 ; extra == 'all'
Requires-Dist: pysbd>=0.3.4 ; extra == 'all'
Requires-Dist: python-slugify>=8.0.4 ; extra == 'all'
Requires-Dist: rapidfuzz>=3.14.3 ; extra == 'all'
Requires-Dist: unidecode>=1.4.0 ; extra == 'all'
Requires-Dist: watchdog>=6.0.0 ; extra == 'all'
Requires-Dist: gitpython>=3.1.46 ; extra == 'all'
Requires-Dist: jinja2>=3.1.6 ; extra == 'all'
Requires-Dist: tenacity>=9.1.3 ; extra == 'all'
Requires-Dist: orjson>=3.11.7 ; extra == 'all'
Requires-Dist: psutil>=7.2.2 ; extra == 'all'
Requires-Dist: lxml>=6.0.2 ; extra == 'all'
Requires-Dist: xmltodict>=1.0.2 ; extra == 'all'
Requires-Dist: python-dateutil>=2.9.0.post0 ; extra == 'all'
Requires-Dist: email-validator>=2.3.0 ; extra == 'all'
Requires-Dist: validators>=0.35.0 ; extra == 'all'
Requires-Dist: numpy>=2.0.0 ; extra == 'all'
Requires-Dist: opencv-python-headless>=4.10.0 ; extra == 'all'
Requires-Dist: duckdb>=1.4.4 ; extra == 'data'
Requires-Dist: polars>=1.38.0 ; extra == 'data'
Requires-Dist: pyarrow>=23.0.0 ; extra == 'data'
Requires-Dist: openpyxl>=3.1.5 ; extra == 'docs'
Requires-Dist: pdfplumber>=0.11.9 ; extra == 'docs'
Requires-Dist: pymupdf>=1.26.7 ; extra == 'docs'
Requires-Dist: pypdf>=6.6.2 ; extra == 'docs'
Requires-Dist: python-docx>=1.2.0 ; extra == 'docs'
Requires-Dist: watchdog>=6.0.0 ; extra == 'fs'
Requires-Dist: gitpython>=3.1.46 ; extra == 'git'
Requires-Dist: google-generativeai>=0.5,<0.6 ; extra == 'google'
Requires-Dist: numpy>=2.0.0 ; extra == 'ocr'
Requires-Dist: opencv-python-headless>=4.10.0 ; extra == 'ocr'
Requires-Dist: orjson>=3.11.7 ; extra == 'ops'
Requires-Dist: psutil>=7.2.2 ; extra == 'ops'
Requires-Dist: tenacity>=9.1.3 ; extra == 'ops'
Requires-Dist: email-validator>=2.3.0 ; extra == 'parse'
Requires-Dist: lxml>=6.0.2 ; extra == 'parse'
Requires-Dist: python-dateutil>=2.9.0.post0 ; extra == 'parse'
Requires-Dist: validators>=0.35.0 ; extra == 'parse'
Requires-Dist: xmltodict>=1.0.2 ; extra == 'parse'
Requires-Dist: jinja2>=3.1.6 ; extra == 'templates'
Requires-Dist: charset-normalizer>=3.4.4 ; extra == 'text'
Requires-Dist: ftfy>=6.3.1 ; extra == 'text'
Requires-Dist: pysbd>=0.3.4 ; extra == 'text'
Requires-Dist: python-slugify>=8.0.4 ; extra == 'text'
Requires-Dist: rapidfuzz>=3.14.3 ; extra == 'text'
Requires-Dist: unidecode>=1.4.0 ; extra == 'text'
Requires-Python: >=3.13, <3.14
Project-URL: Homepage, https://github.com/albusstudio/albusOS
Project-URL: Repository, https://github.com/albusstudio/albusOS
Project-URL: Issues, https://github.com/albusstudio/albusOS/issues
Provides-Extra: a2a
Provides-Extra: all
Provides-Extra: data
Provides-Extra: docs
Provides-Extra: fs
Provides-Extra: git
Provides-Extra: google
Provides-Extra: ocr
Provides-Extra: ops
Provides-Extra: parse
Provides-Extra: templates
Provides-Extra: text
Description-Content-Type: text/markdown

# AlbusOS

AI agent runtime framework. Install it, bring your own domain.

```
pip install albusos
```

---

## What is AlbusOS?

AlbusOS is a **domain-agnostic agent execution framework**. It provides the runtime, pathway VM, and transport layer. You provide the domain content — agents, skills, tools, and pathways specific to your problem.

```
albusOS (the framework)                Your repo (the domain)
├── core/        Pathways VM, nodes    ├── skills/      SKILL.md + tools/
├── stdlib/      LLM routing, tools    ├── pathways/    Workflow YAMLs
├── server/      HTTP, CLI, loaders    └── albus.yaml   Deployment config
├── infrastructure/  Sandbox, MCP
└── persistence/ State store
```

**albusOS handles:** Runtime, pathway VM, LLM provider routing, core tools (memory, web, workspace, shell, code execution), observability, state management, HTTP/WebSocket/CLI transport.

**Your repo handles:** Domain-specific agents, skills, tools, and pathway workflows.

---

## Quick Start

**Requires Python 3.13+**

### From scratch

```bash
mkdir my-agent-service && cd my-agent-service
pip install albusos
albus init

# Add your API key
cp env.example .env
# Edit .env: OPENROUTER_API_KEY=sk-or-...

# Try it
albus chat "Hello, what can you do?"
```

### From an existing Python codebase

If you already have a Python service (FastAPI, MCP server, CLI tools), scan it
to auto-generate skills:

```bash
pip install albusos
albus init --scan /path/to/your/python/code
```

This reads your codebase via AST (no execution), detects tool-like functions,
and generates `skills/<namespace>/tools/*.py` wrappers plus an `albus.yaml`
with all discovered tools wired up.

---

## Development Workflow

AlbusOS follows a **design → develop → deploy** workflow.

### 1. Design — scan and discover

```bash
albus init --scan /path/to/client/code    # Generate skills from existing code
albus list tools                          # See what was discovered
```

### 2. Develop — build with the fluent API

The fluent API is the primary authoring experience. Write pathways and agents
in Python, test them, iterate.

```python
from albusos import PathwayBuilder, AgentBuilder, ToolOutput

# Build a pathway — validated at construction time
dispatch = (
    PathwayBuilder("dispatch", pathway_id="dispatch")
    .stateful()
    .tool("fetch_jobs", "servicem8.list_jobs")
    .tool("check_schedule", "servicem8.check_schedule")
    .llm("rank", "Rank technicians by fit for: {{fetch_jobs.output}}")
    .connect("input", "fetch_jobs")
    .connect("fetch_jobs", "check_schedule")
    .connect("check_schedule", "rank")
    .connect("rank", "output")
    .build()
)

# Build an agent
dispatch_agent = (
    AgentBuilder()
    .id("dispatch")
    .name("Dispatch Agent")
    .instructions("Schedule technicians to jobs based on skills and availability.")
    .tool("servicem8.*")
    .tool("memory.*")
    .pathway("dispatch")
    .model("reasoning")
    .build()
)
```

### 3. Deploy — compile to YAML, ship

```python
# Export pathway to YAML for deployment
dispatch.to_yaml()  # → pathways/dispatch.yaml
```

The client receives `albus.yaml` + `skills/` + `pathways/` and runs:

```bash
albus server    # HTTP + WebSocket server, ready to go
```

---

## Writing Tools

Each tool is a single Python file with an `async def run()` function:

```python
"""Discover available ServiceM8 resources."""

from albusos import ToolOutput


async def run(context=None) -> ToolOutput:
    """List all available API resources.

    Args: (none)
    """
    resources = await fetch_resources()
    return ToolOutput(success=True, data={"resources": resources})
```

Place tools inside a skill directory:

```
skills/
└── servicem8/
    ├── SKILL.md              # Instructions for the agent
    └── tools/
        ├── discovery.py      # → servicem8.discovery
        ├── crud.py           # → servicem8.crud
        └── triage.py         # → servicem8.triage
```

Tools are auto-discovered and named `{skill}.{file}`. No decorators, no
registration, no class hierarchies.

---

## Configuring Agents

In `albus.yaml` (the deployment config):

```yaml
agents:
  - id: host
    name: ServiceM8 Assistant
    tools: ["servicem8.*", "memory.*", "web.*"]
    pathway: react
    max_steps: 10
    model: reasoning
```

Or programmatically via the fluent API (see Development Workflow above).

---

## Pathways

Pathways are the composition language — DAGs or stateful graphs of nodes.
**You write pathways for your domain workflows. That's the product.**

### Building pathways

Use the fluent API for authoring:

```python
from albusos import PathwayBuilder

pipeline = (
    PathwayBuilder("research")
    .tool("search", "web.search", args={"query": "{{input.query}}"})
    .llm("summarize", "Summarize: {{search.output}}", model="reasoning")
    .connect("input", "search")
    .connect("search", "summarize")
    .connect("summarize", "output")
    .build()
)
```

Or write YAML directly for deployment:

```yaml
# pathways/dispatch.yaml
name: dispatch
mode: stateful
nodes:
  - id: fetch_jobs
    type: tool
    config: { tool: servicem8.list_jobs }
  - id: rank_candidates
    type: llm
    config: { prompt: "Rank technicians by fit..." }
  - id: propose
    type: checkpoint
    config: { require_approval: true }
  - id: assign
    type: tool
    config: { tool: servicem8.assign_job }
connections:
  - { from: fetch_jobs, to: rank_candidates }
  - { from: rank_candidates, to: propose }
  - { from: propose, to: assign }
```

### Node types

| Type | Purpose | Example |
|------|---------|---------|
| `input` | Declare pathway inputs | `{"type": "input", "config": {"input_schema": {...}}}` |
| `output` | Map pathway outputs | `{"type": "output", "config": {"mapping": {...}}}` |
| `tool` | Call any registered tool | `{"type": "tool", "config": {"tool": "web.search", "args": {...}}}` |
| `llm` | Direct LLM call | `{"type": "llm", "config": {"prompt": "..."}}` |
| `agent` | Agent-in-a-box | `{"type": "agent", "config": {"goal": "...", "tools": [...]}}` |
| `pathway` | Nested sub-pathway | `{"type": "pathway", "config": {"pathway_id": "research"}}` |
| `checkpoint` | Human-in-the-loop | `{"type": "checkpoint", "config": {"require_approval": true}}` |
| `transform` | Expression evaluation | `{"type": "transform", "config": {"expr": "a + b"}}` |
| `conditional` | Branching logic | `{"type": "conditional", "config": {"condition": "..."}}` |
| `handoff` | Route to another agent | `{"type": "handoff", "config": {"target_agent": "..."}}` |
| `stage` | Group nodes into phases | `{"type": "stage", "config": {"name": "planning"}}` |
| `loop` | Iterate over items | `{"type": "loop", "config": {"max_iterations": 5}}` |

### Execution modes

| Mode | Behavior | Use when |
|------|----------|----------|
| `dag` (default) | Parallel, no cycles | Data pipelines, fan-out/fan-in |
| `stateful` | Sequential, cycles OK | Conversations, human-in-the-loop |

---

## Architecture

### Package structure

```
src/
├── albusos/           Public API (from albusos import ...)
├── core/              Pathways, nodes, protocols, types, state
│   ├── pathways/          Pathway VM, nodes, session, store
│   ├── builders/          Fluent builders (PathwayBuilder, AgentBuilder, SkillBuilder)
│   ├── types/             Pydantic models (AgentDefinition, ExecutionBudget, etc.)
│   ├── protocols/         Abstract interfaces (PathwayVMLike, StateStoreLike)
│   ├── registry.py        Unified Registry (ToolRegistry + SkillRegistry)
│   └── agent.py           Agent (runtime entity) + AgentRepository
├── stdlib/            Standard library
│   ├── llm/               LLM providers (OpenAI, OpenRouter, Ollama)
│   ├── primitives/        Built-in tools (loaded via load_stdlib())
│   │   ├── tools/         web, workspace, memory, shell
│   │   ├── orchestration/ agent.turn, agent.list
│   │   └── code/          code.execute, code.run_test
│   └── bootstrap.py       load_stdlib() — registers primitives into ToolRegistry
├── server/            Server infrastructure
│   ├── runtime.py         Runtime — server factory, turn execution, component wiring
│   ├── config/            Deployment config, env resolution
│   ├── loaders/           Load agents, skills, tools, pathways from disk
│   └── transport/         HTTP server, WebSocket (studio), A2A, CLI
├── infrastructure/    Sandbox (Python runner), MCP client, tool loader
└── persistence/       File-based state store
```

### Key imports

```python
# Development API (authoring agents, pathways, tools)
from albusos import PathwayBuilder, AgentBuilder, SkillBuilder
from albusos import AgentDefinition, Pathway, PathwayMode
from albusos import ToolOutput, ToolRegistry, get_tool_registry, load_stdlib

# Runtime API (executing agents and pathways)
from albusos import chat, run, create_server
from albusos import ExecutionResult, ExecutionBudget, ThreadState

# Direct module access (when you need internals)
from server.runtime import Runtime
from core.builders import PathwayBuilder, AgentBuilder, SkillBuilder
from stdlib.llm.routing import get_model_for_capability, ModelCapability
```

---

## Model Routing

Capability-based model selection via `config/models.yaml` or runtime config:

| Capability | Use for | Default |
|------------|---------|---------|
| `fast` | Quick tasks, routing | openai/gpt-4o-mini |
| `reasoning` | Complex thinking | anthropic/claude-sonnet-4 |
| `code` | Code generation | anthropic/claude-sonnet-4 |
| `vision` | Image understanding | openai/gpt-4o |
| `local` | Offline/free | llama3.1:8b (Ollama) |

```python
# In agent configs or pathway nodes
model = "reasoning"        # Capability name (recommended)
model = "openai/gpt-4o"   # Explicit model (OpenRouter format)
```

---

## CLI

```bash
albus init                          # Initialize workspace
albus init --scan /path/to/code     # Scan codebase, generate skills
albus chat                          # Interactive agent chat
albus chat "do something"           # One-shot agent turn
albus run pathway.yaml              # Execute a pathway
albus server                        # Start HTTP + WebSocket server
albus list tools                    # List registered tools
albus list skills                   # List loaded skills
albus pathway validate file.yaml    # Validate pathway structure
albus pathway new my-workflow       # Scaffold a new pathway
albus tool run web.search --query "test"   # Run a tool directly
```

## API Endpoints

| Endpoint | Description |
|----------|-------------|
| `GET /api/v1/health` | Health check |
| `GET /api/v1/tools` | List tools |
| `POST /api/v1/tools/{name}` | Execute a tool |
| `GET /api/v1/agents` | List agents |
| `POST /api/v1/agents/{id}/turn` | Run agent turn |
| `GET /api/v1/pathways` | List pathways |
| `GET /api/v1/pathways/{id}` | Get pathway details |
| `POST /api/v1/pathways/{id}/run` | Run pathway |
| `GET /api/v1/pathways/{id}/export` | Export pathway JSON |
| `GET /api/v1/pathways/{id}/graph` | Pathway graph structure |

---

## License

MIT
