Metadata-Version: 2.4
Name: arbis
Version: 0.4.5
Summary: Runtime workflow observation for agent systems.
License: MIT
Keywords: observability,workflow,agents,tracing,llm
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: respx>=0.20; extra == "dev"
Requires-Dist: python-dotenv>=1.0; extra == "dev"
Requires-Dist: openai<2.31.0,>=2.30.0; extra == "dev"
Requires-Dist: jiter<0.14.0,>=0.13.0; extra == "dev"
Requires-Dist: httpx>=0.24; extra == "dev"
Provides-Extra: arbis-litellm
Requires-Dist: litellm; python_version >= "3.11" and extra == "arbis-litellm"
Provides-Extra: arbis-openrouter
Requires-Dist: openrouter>=0.8.0; python_version >= "3.9" and extra == "arbis-openrouter"
Provides-Extra: arbis-gemini
Requires-Dist: google-generativeai>=0.7.0; python_version >= "3.9" and extra == "arbis-gemini"
Provides-Extra: arbis-bedrock
Requires-Dist: boto3>=1.28; python_version >= "3.8" and extra == "arbis-bedrock"
Provides-Extra: arbis-frameworks
Requires-Dist: langchain<0.4,>=0.3; python_version >= "3.11" and extra == "arbis-frameworks"
Requires-Dist: langchain-community<0.4,>=0.3; python_version >= "3.11" and extra == "arbis-frameworks"
Requires-Dist: langchain-core<1,>=0.3.85; python_version >= "3.11" and extra == "arbis-frameworks"
Requires-Dist: langchain-openai<0.4,>=0.3; python_version >= "3.11" and extra == "arbis-frameworks"
Requires-Dist: langgraph<0.7,>=0.6; python_version >= "3.11" and extra == "arbis-frameworks"
Requires-Dist: autogen-agentchat<0.3,>=0.2.40; python_version >= "3.11" and extra == "arbis-frameworks"
Provides-Extra: arbis-crewai
Requires-Dist: crewai>=0.80; python_version >= "3.11" and extra == "arbis-crewai"
Provides-Extra: arbis-llamaindex
Requires-Dist: llama-index-core<0.15,>=0.14; python_version >= "3.11" and extra == "arbis-llamaindex"
Requires-Dist: llama-index-llms-openai<0.8,>=0.7; python_version >= "3.11" and extra == "arbis-llamaindex"
Provides-Extra: arbis-openai-agents
Requires-Dist: openai-agents>=0.3; python_version >= "3.11" and extra == "arbis-openai-agents"
Provides-Extra: arbis-live
Requires-Dist: anthropic>=0.40; python_version >= "3.9" and extra == "arbis-live"
Requires-Dist: boto3>=1.28; python_version >= "3.8" and extra == "arbis-live"
Requires-Dist: google-genai>=1.0; python_version >= "3.10" and extra == "arbis-live"
Requires-Dist: google-generativeai>=0.7.0; python_version >= "3.9" and extra == "arbis-live"
Requires-Dist: openrouter>=0.8.0; python_version >= "3.9" and extra == "arbis-live"
Requires-Dist: litellm; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: langchain<0.4,>=0.3; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: langchain-community<0.4,>=0.3; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: langchain-core<1,>=0.3.85; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: langchain-openai<0.4,>=0.3; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: langgraph<0.7,>=0.6; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: autogen-agentchat<0.3,>=0.2.40; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: crewai>=0.80; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: llama-index-core<0.15,>=0.14; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: llama-index-llms-openai<0.8,>=0.7; python_version >= "3.11" and extra == "arbis-live"
Requires-Dist: openai-agents>=0.3; python_version >= "3.11" and extra == "arbis-live"
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.20; extra == "otel"
Requires-Dist: opentelemetry-sdk>=1.20; extra == "otel"
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20; extra == "otel"
Dynamic: license-file

# arbis

Runtime workflow observation for agent systems.

Arbis instruments SDK boundaries, collects execution events, and infers workflow graphs from observed behavior. It reconstructs what happened during representative executions without requiring manual instrumentation of every call.

## Install

```bash
pip install arbis
```

## Quick Start

```python
import arbis

# Start observing — instruments OpenAI, Anthropic, Gemini, Bedrock,
# OpenRouter, LiteLLM, LangChain, CrewAI, AutoGen, LlamaIndex, and more.
tracker = arbis.discover()

# ... run your agent code as normal ...

# Stop and get the inferred workflow graph.
tracker.stop()
graph = tracker.graph()
print(f"{len(graph.nodes)} nodes, {len(graph.edges)} edges")
```

That's it. No decorators required for basic observation — `discover()` patches supported SDK boundaries automatically.

## What Gets Captured

| Layer | Automatic | Explicit API needed |
|-------|-----------|---------------------|
| LLM calls (input, output, tokens, tools, thinking) | Yes | — |
| Streaming (sync + async) | Yes | — |
| Tool call loops (ReAct) | Yes | — |
| Agent groups and handoffs | Yes | — |
| Multi-agent orchestration topology | Yes | — |
| Named workflows / agents | — | `@arbis.workflow`, `@arbis.agent` |
| Declared handoffs between known agents | — | `arbis.step("handoff", input_data={"from": ..., "to": ...})` |
| Custom tool spans | — | `@arbis.tool`, `tracker.tool_call(...)` |
| Routing decisions | — | `arbis.route(...)` |
| Human-in-the-loop gates | — | `arbis.human_input(...)` |

## Supported Providers & Frameworks

**LLM Providers:**
- OpenAI (Chat Completions, Responses API, Embeddings)
- OpenAI Agents SDK
- Anthropic Messages
- Google Gemini (`google.generativeai` and `google.genai`)
- AWS Bedrock (Converse / Converse Stream)
- OpenRouter
- LiteLLM

**Orchestration Frameworks:**
- LangChain / LangGraph
- CrewAI
- AutoGen
- LlamaIndex

**Transport:**
- `httpx` and `requests` (HTTP-level LLM detection and tool execution spans)

## Explicit Context API

For richer graphs, add structure with decorators:

```python
import arbis

tracker = arbis.discover()

@arbis.workflow("loan_processing")
def process_loan(application):

    @arbis.agent("underwriter")
    def underwrite():
        # LLM calls here are automatically grouped under this agent
        ...

    @arbis.tool("credit_check")
    def check_credit(applicant_id):
        # Tool execution captured as a first-class span
        ...

    underwrite()
    check_credit(application["id"])

process_loan(app)
tracker.stop()
```

## Persistence

Save workflow runs for later analysis:

```python
# SQLite (default file-based)
tracker = arbis.discover(store="workflows.sqlite")

# JSON directory
tracker = arbis.discover(store="output/", store_backend="json")

# PostgreSQL (requires: pip install 'arbis[postgres]')
tracker = arbis.discover(store="postgresql://user:pass@host/db", store_backend="postgres")

# HTTP ingest to the Arbis backend (minted workflow_id / agent_id on @workflow / @agent)
tracker = arbis.discover(store_backend="http", org_id=ORG_ID, project_id=PROJECT_ID)
```

See [minted-identities.md](docs/minted-identities.md) for attaching dashboard UUIDs
and for identity-force-mode ingest warnings.

## Export to OpenTelemetry

Mirror runs to OpenTelemetry as **traces** (the `workflow → agent → llm_call → tool`
span tree, for Jaeger/Tempo/Honeycomb/Datadog) and/or **metrics** (token usage,
latency, call/error/retry counts) — independently of, or alongside, Arbis's own
stores. Requires `pip install 'arbis[otel]'`.

```python
import arbis

# Arbis-owned OTLP export to a collector/Jaeger
tracker = arbis.discover(otel=True, otel_endpoint="localhost:4317")

# Add metrics, and/or plug into your existing OpenTelemetry providers
from opentelemetry import trace, metrics
tracker = arbis.discover(
    otel=True, otel_metrics=True,
    otel_tracer_provider=trace.get_tracer_provider(),
    otel_meter_provider=metrics.get_meter_provider(),
)
```

Spans follow OTel GenAI semantic conventions plus an `arbis.*` namespace. See the
[OpenTelemetry section of the guide](docs/guide.md#export-to-opentelemetry)
for setup, both export modes, and the attribute/metric reference.

## Workflow Viewer (TUI)

Browse workflow definitions, run history, and agent topology in the terminal:

```bash
pip install textual rich
python -m arbis.viewer
```

The viewer launches with realistic demo data by default. To connect to a live PostgreSQL store:

```bash
# Set connection details
export ARBIS_POSTGRES_DSN="postgresql://user:pass@host/db"
export ARBIS_PROJECT_ID="your-project-uuid"

# Initialize the database (first time only)
psql -d arbis -f scripts/init_db.sql
# Or reset from scratch:
./scripts/reset_db.sh

# Launch
python -m arbis.viewer --store "$ARBIS_POSTGRES_DSN" --project-id "$ARBIS_PROJECT_ID"
```

**Viewer keybindings:**

| Key | Action |
|-----|--------|
| Arrow keys | Navigate |
| Enter | Select / drill in |
| Escape | Back |
| `d` | Diff workflow versions |
| `n` | Rename workflow or agent |
| `l` | View lineage link suggestions |
| `c` | Compliance breakdown |
| `r` | Refresh data |
| `q` | Quit |

**Three-pane layout:**
- **Left:** Workflow definitions (named or auto-discovered)
- **Middle:** Run history for the selected workflow
- **Right:** Run detail — agent groups, handoffs, tool calls, thinking traces, token usage, and event timeline

## Workflow Diffing

Compare how workflows evolve over time:

```python
import arbis

diff_result = arbis.diff(graph_a, graph_b)
# Returns structural fingerprint comparison, agent/tool changes, topology deltas
```

In the viewer, press `d` on a workflow with multiple versions to see agent prompt changes, topology edits, and performance deltas.

## Optional Dependencies

```bash
pip install 'arbis[postgres]'         # PostgreSQL storage backend
pip install 'arbis[otel]'             # OpenTelemetry traces + metrics export
pip install 'arbis[dev]'              # Development & testing
pip install 'arbis[arbis-litellm]'    # LiteLLM support
pip install 'arbis[arbis-frameworks]' # LangChain + AutoGen
pip install 'arbis[arbis-crewai]'     # CrewAI
pip install 'arbis[arbis-llamaindex]' # LlamaIndex
pip install 'arbis[arbis-bedrock]'    # AWS Bedrock
pip install 'arbis[arbis-gemini]'     # Google Gemini SDK
```

## Documentation

All documentation is bundled inside the installed package. After `pip install arbis`:

```python
from importlib.resources import files

# Get the path to bundled docs
docs = files("arbis") / "docs"

# Read a specific doc
print((docs / "guide.md").read_text())
```

**Bundled docs:**

| File | Contents |
|------|----------|
| `docs/SKILL.md` | Complete API reference — 17 integration patterns covering every public API |
| `docs/guide.md` | Mental model, automatic vs explicit matrix, SDK coverage |
| `docs/architecture.md` | Module map, instrumentor details, inference pipeline |
| `docs/overview.md` | Overview: workflows, tools, supported SDKs/frameworks, and performance |
| `docs/viewer-guide.md` | TUI viewer usage, PostgreSQL setup, layout and navigation |
| `docs/streaming-runs.md` | HTTP streaming ingest + `arbis.wait` |
| `docs/minted-identities.md` | Minted `workflow_id` / `agent_id`, identity force mode, ingest 400s |

## License

MIT. See [LICENSE](LICENSE).
