Metadata-Version: 2.4
Name: locus-sdk
Version: 0.2.0b5
Summary: Multi-agent workflows for Python — stream them, branch them, pause for a human, resume next week. Built on Oracle Generative AI.
Project-URL: Homepage, https://github.com/oracle-samples/locus
Project-URL: Documentation, https://github.com/oracle-samples/locus#readme
Project-URL: Repository, https://github.com/oracle-samples/locus
Project-URL: Issues, https://github.com/oracle-samples/locus/issues
Author: Federico Kamelhar
License-Expression: UPL-1.0
License-File: LICENSE
License-File: LICENSE.txt
Keywords: agents,ai,llm,orchestration,pydantic,react,reflexion
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Universal Permissive License (UPL)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: pydantic>=2.0
Requires-Dist: typing-extensions>=4.0
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
Provides-Extra: checkpoints
Requires-Dist: aiosqlite>=0.20; extra == 'checkpoints'
Requires-Dist: asyncpg>=0.29; extra == 'checkpoints'
Requires-Dist: oci>=2.173.0; extra == 'checkpoints'
Requires-Dist: opensearch-py>=2.4; extra == 'checkpoints'
Requires-Dist: oracledb>=2.2.0; extra == 'checkpoints'
Requires-Dist: redis>=5.0; extra == 'checkpoints'
Provides-Extra: chroma
Requires-Dist: chromadb>=0.5; extra == 'chroma'
Provides-Extra: dev
Requires-Dist: aiosqlite>=0.22.1; extra == 'dev'
Requires-Dist: dirty-equals>=0.8; extra == 'dev'
Requires-Dist: fastmcp>=3.2.0; extra == 'dev'
Requires-Dist: hatch>=1.12; extra == 'dev'
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pre-commit>=3.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.5; extra == 'dev'
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Requires-Dist: pyyaml>=6.0.3; extra == 'dev'
Requires-Dist: redis>=7.1.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Requires-Dist: sqlalchemy>=2.0.46; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.27; extra == 'docs'
Provides-Extra: llm
Requires-Dist: anthropic>=0.40; extra == 'llm'
Requires-Dist: oci>=2.173.0; extra == 'llm'
Requires-Dist: ollama>=0.3; extra == 'llm'
Requires-Dist: openai>=1.50; extra == 'llm'
Provides-Extra: mcp
Requires-Dist: mcp>=1.0; extra == 'mcp'
Provides-Extra: oci
Requires-Dist: oci>=2.173.0; extra == 'oci'
Provides-Extra: ollama
Requires-Dist: ollama>=0.3; extra == 'ollama'
Provides-Extra: openai
Requires-Dist: openai>=1.50; extra == 'openai'
Provides-Extra: opensearch
Requires-Dist: opensearch-py>=2.4; extra == 'opensearch'
Provides-Extra: oracledb
Requires-Dist: oracledb>=2.2.0; extra == 'oracledb'
Provides-Extra: pgvector
Requires-Dist: asyncpg>=0.29; extra == 'pgvector'
Provides-Extra: pinecone
Requires-Dist: pinecone>=5.0; extra == 'pinecone'
Provides-Extra: postgresql
Requires-Dist: asyncpg>=0.29; extra == 'postgresql'
Provides-Extra: qdrant
Requires-Dist: qdrant-client>=1.11; extra == 'qdrant'
Provides-Extra: rag
Requires-Dist: aiosqlite>=0.20; extra == 'rag'
Requires-Dist: asyncpg>=0.29; extra == 'rag'
Requires-Dist: chromadb>=0.5; extra == 'rag'
Requires-Dist: oci>=2.173.0; extra == 'rag'
Requires-Dist: openai>=1.50; extra == 'rag'
Requires-Dist: opensearch-py>=2.4; extra == 'rag'
Requires-Dist: oracledb>=2.2.0; extra == 'rag'
Requires-Dist: pinecone>=5.0; extra == 'rag'
Requires-Dist: qdrant-client>=1.11; extra == 'rag'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Provides-Extra: sdk
Requires-Dist: aiosqlite>=0.20; extra == 'sdk'
Requires-Dist: anthropic>=0.40; extra == 'sdk'
Requires-Dist: asyncpg>=0.29; extra == 'sdk'
Requires-Dist: chromadb>=0.5; extra == 'sdk'
Requires-Dist: fastapi>=0.110; extra == 'sdk'
Requires-Dist: mcp>=1.0; extra == 'sdk'
Requires-Dist: oci>=2.173.0; extra == 'sdk'
Requires-Dist: ollama>=0.3; extra == 'sdk'
Requires-Dist: openai>=1.50; extra == 'sdk'
Requires-Dist: opensearch-py>=2.4; extra == 'sdk'
Requires-Dist: opentelemetry-api>=1.20; extra == 'sdk'
Requires-Dist: opentelemetry-exporter-otlp>=1.20; extra == 'sdk'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'sdk'
Requires-Dist: oracledb>=2.2.0; extra == 'sdk'
Requires-Dist: pinecone>=5.0; extra == 'sdk'
Requires-Dist: qdrant-client>=1.11; extra == 'sdk'
Requires-Dist: redis>=5.0; extra == 'sdk'
Requires-Dist: uvicorn[standard]>=0.27; extra == 'sdk'
Provides-Extra: server
Requires-Dist: fastapi>=0.110; extra == 'server'
Requires-Dist: uvicorn[standard]>=0.27; extra == 'server'
Provides-Extra: sqlite
Requires-Dist: aiosqlite>=0.20; extra == 'sqlite'
Provides-Extra: telemetry
Requires-Dist: opentelemetry-api>=1.20; extra == 'telemetry'
Requires-Dist: opentelemetry-exporter-otlp>=1.20; extra == 'telemetry'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'telemetry'
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://raw.githubusercontent.com/oracle-samples/locus/main/docs/img/logo.svg" alt="locus — Multi-Agent Reasoning Orchestrator SDK" width="320">
</p>

<p align="center">
  <strong>Oracle Generative AI · Multi-Agent Reasoning Orchestrator SDK</strong><br>
  <em>Built inside Oracle. Used in production. Open to everyone.</em>
</p>

<p align="center">
  <img src="https://img.shields.io/badge/Python-3.11%E2%80%933.14-blue.svg" alt="Python 3.11–3.14">
  <img src="https://img.shields.io/badge/License-UPL--1.0-green.svg" alt="License">
  <img src="https://img.shields.io/badge/mypy-strict-brightgreen.svg" alt="mypy strict">
  <img src="https://img.shields.io/badge/ruff-clean-brightgreen.svg" alt="ruff clean">
  <img src="https://img.shields.io/badge/OCI%20GenAI-day%200-orange.svg" alt="OCI GenAI day-0">
</p>

<p align="center">
  <a href="https://oracle-samples.github.io/locus/">Documentation</a> ·
  <a href="https://oracle-samples.github.io/locus/concepts/router/">Cognitive Router</a> ·
  <a href="https://oracle-samples.github.io/locus/concepts/multi-agent/">Multi-agent</a> ·
  <a href="https://oracle-samples.github.io/locus/concepts/deepagent/">DeepAgent</a> ·
  <a href="examples/">56 Tutorials</a> ·
  <a href="workbench/">Workbench</a>
</p>

<p align="center">
  <a href="https://codespaces.new/oracle-samples/locus?devcontainer_path=.devcontainer%2Fdevcontainer.json">
    <img src="https://github.com/codespaces/badge.svg" alt="Open in GitHub Codespaces">
  </a>
</p>

---

## Your first agent — 5 lines

```python
from locus import Agent

agent = Agent(model="oci:openai.gpt-5")
print(agent.run_sync("What is the capital of France?").text)
# → Paris
```

That's it. `Agent` handles the model call, the response, and any retries.
Swap `"oci:openai.gpt-5"` for `"openai:gpt-4o"` or `"anthropic:claude-sonnet-4-6"` — the interface stays the same.

## Add a tool

Tools are plain Python functions. The model sees the docstring and decides when to call them.

```python
from locus import Agent, tool

@tool
def get_weather(city: str) -> str:
    """Return the current weather for a city."""
    return weather_api.fetch(city)

agent = Agent(
    model="oci:openai.gpt-5",
    tools=[get_weather],
    system_prompt="You are a helpful travel assistant.",
)

print(agent.run_sync("Should I bring an umbrella to Tokyo tomorrow?").text)
```

The agent loops — Think → call tool → Think → answer — until it's done.
Add `@tool(idempotent=True)` to any tool that must not fire twice (bookings, payments, alerts).
The loop dedupes on `(name, args)` so retries are safe by design.

## Install

```bash
pip install "locus-sdk[oci]"           # OCI GenAI (90+ models, day-0)
pip install "locus-sdk[openai]"        # OpenAI
pip install "locus-sdk[anthropic]"     # Anthropic
pip install "locus-sdk[sdk]"           # everything
```

No mandatory cloud account to start — `MockModel` lets every tutorial run offline.

---

## The cognitive router — describe what you need, get the right shape

Once you know agents, the next step is knowing *which* shape to use.
The cognitive router takes a natural-language task, selects from eight proven coordination patterns,
and instantiates the right primitive — without you hand-coding the topology.

```python
from locus.deepagent.workflow import create_research_workflow, KEY_PROMPT

workflow = create_research_workflow(
    model=get_model(),
    tools=[web_search, web_fetch],
    grounding_threshold=0.65,
)

result = await workflow.execute({KEY_PROMPT: "What happened in mathematics in 2026?"})
print(result.final_state["summary"])
```

The workflow runs: **execute (ReAct)** → **causal inference** → **summarize** → **grounding eval** →
lightweight **regenerate** or full **replan** if grounding is too low.
Every step emits `research.*` SSE events you can stream in real time.

→ [Cognitive router concept](https://oracle-samples.github.io/locus/concepts/router/) ·
[Research workflow](https://oracle-samples.github.io/locus/concepts/deepagent/)

---

## Seven coordination patterns

When one agent isn't enough, locus gives you seven in-process shapes plus cross-process A2A.
Every pattern uses the same `Agent` class and the same event stream.

| Pattern | When to use |
|---|---|
| **SequentialPipeline** | A → B → C in order; each output feeds the next |
| **ParallelPipeline** | Fan out to N agents simultaneously, merge results |
| **LoopAgent** | Refine until a condition fires (PASS/FAIL, confidence, iteration cap) |
| **Orchestrator + Specialists** | One coordinator routes to domain experts in parallel |
| **Swarm** | Open-ended research; peers share a task queue and context |
| **Handoff** | Escalation desk; conversation moves with full history to the next specialist |
| **StateGraph** | Explicit DAG with conditional edges, cycles, and human-in-the-loop gates |
| **A2A** | Cross-process meshes over HTTP; agents advertise capabilities via AgentCard |

```python
from locus import Agent, SequentialPipeline

researcher = Agent(model=model, system_prompt="Find three key facts about the topic.")
critic     = Agent(model=model, system_prompt="Identify any gaps or errors in the research.")
writer     = Agent(model=model, system_prompt="Write a clear one-paragraph summary.")

result = await SequentialPipeline(agents=[researcher, critic, writer]).run(
    "Explain quantum entanglement to a high-schooler."
)
print(result.text)
```

→ [All patterns](https://oracle-samples.github.io/locus/concepts/multi-agent/)

---

## What you get

| | |
|---|---|
| **[🧭 Cognitive router](https://oracle-samples.github.io/locus/concepts/router/)** | Describe a task → eight named protocols → right primitive compiled automatically. LLM fills a typed schema; routing is deterministic. |
| **[🤝 Multi-agent](https://oracle-samples.github.io/locus/concepts/multi-agent/)** | Seven native patterns + cross-process A2A. One `Agent` class. One event stream. |
| **[🔬 DeepAgent](https://oracle-samples.github.io/locus/concepts/deepagent/)** | `create_deepagent` (single agent, per-turn grounding) and `create_research_workflow` (StateGraph with post-hoc grounding eval + two-level recovery). |
| **[📡 Observability](https://oracle-samples.github.io/locus/concepts/observability/)** | Opt-in `EventBus` — one `run_context()` streams 40+ canonical events from every layer, no external broker. `TelemetryHook` for OpenTelemetry/OTLP. |
| **[🧠 Reasoning](https://oracle-samples.github.io/locus/concepts/reasoning/)** | `reflexion=True` · `grounding=True` · `CausalChain` · **GSAR** typed grounding layer (`arXiv:2604.23366`). |
| **[🛡 Idempotent tools](https://oracle-samples.github.io/locus/concepts/idempotency/)** | `@tool(idempotent=True)` — dedupes on `(name, args)`. The model can't double-charge, double-book, or double-page. |
| **[💾 Durable memory](https://oracle-samples.github.io/locus/concepts/checkpointers/)** | 9 backends — OCI Object Storage, PostgreSQL, Redis, SQLite, Oracle 26ai, OpenSearch, in-memory, file, HTTP. |
| **[🔎 RAG](https://oracle-samples.github.io/locus/concepts/rag/)** | 7 vector stores · OCI Cohere + OpenAI embeddings · multimodal (PDF, image OCR, audio). |
| **[📡 Streaming + Server](https://oracle-samples.github.io/locus/concepts/server/)** | Typed events · SSE · `AgentServer` (FastAPI, per-principal thread isolation). |
| **[🪝 Hooks](https://oracle-samples.github.io/locus/concepts/hooks/)** | Logging · OpenTelemetry · ModelRetry · Guardrails · Steering (LLM-as-judge). |
| **[🪙 MCP](https://oracle-samples.github.io/locus/concepts/mcp/)** | `MCPClient` consumes MCP servers. `LocusMCPServer` exposes locus tools as MCP. |
| **[🌐 Multi-modal](https://oracle-samples.github.io/locus/concepts/multi-modal-providers/)** | `Agent(web_search=…, web_fetch=…, image_generator=…, speech_provider=…)` auto-registers tools. |
| **[📊 Evaluation](https://oracle-samples.github.io/locus/concepts/evaluation/)** | `EvalCase` / `EvalRunner` / `EvalReport` regression suites. |
| **[🧰 Models](https://oracle-samples.github.io/locus/concepts/models/)** | OCI GenAI (90+ models, V1 + SDK) · OpenAI · Anthropic · Ollama. |

---

## The agent loop

Every locus agent runs the same four-node loop —
**Think → Execute → Reflect → Terminate** — with one immutable state flowing through.

<p align="center">
  <img src="docs/img/agent-loop.svg" alt="Locus agent loop: Think → Execute → Reflect → Terminate" width="100%">
</p>

- **Think** — model decides the next action or final answer.
- **Execute** — runs tool calls in parallel; `@tool(idempotent=True)` dedupes on `(name, args)`.
- **Reflect** — Reflexion, Grounding, Causal on cadence or on error.
- **Terminate?** — typed stop conditions: `MaxIterations(10) | ToolCalled("submit") & ConfidenceMet(0.9)`.

Every node emits a write-protected typed event — same stream powers SSE, telemetry hooks, and your own `async for event in agent.run(…)` consumer.

---

## 56 tutorials

[`examples/`](examples/) has 56 progressive tutorials, each a single runnable file.
Every tutorial runs offline with `MockModel`; set one env var to upgrade to a real provider.

```bash
git clone https://github.com/oracle-samples/locus.git
cd locus && pip install -e .

python examples/tutorial_01_basic_agent.py          # start here
python examples/tutorial_02_agent_with_tools.py     # add tools
python examples/tutorial_41_deepagent.py            # deep research
python examples/tutorial_51_cognitive_router.py     # routing
python examples/tutorial_56_research_workflow.py    # full research pipeline
```

| Track | What you learn |
|---|---|
| **Foundations** (01–05, 21, 27, 28, 37) | Agent, tools, memory, streaming, hooks, server, termination |
| **Graphs** (06–10, 25, 35, 36) | StateGraph, conditional routing, reducers, HITL, composition |
| **Multi-agent** (11, 16–18, 34, 41–45) | Swarm, handoff, orchestrator, A2A, DeepAgent, real-world crews |
| **Reasoning** (13, 14, 39) | Structured output, reflexion + grounding, GSAR typed grounding |
| **RAG** (22–24) | Basics, providers, RAG agents |
| **Skills, playbooks, plugins** (12, 15, 31–33) | MCP, playbooks, plugins, steering |
| **Production** (19, 20, 26, 29, 30, 38, 40) | Guardrails, checkpoints, evaluation, model providers, DAC |
| **Real-world workflows** (46–50) | Incident response, procurement, contract review, audio |
| **Cognitive router + observability** (51–56) | Routing, EventBus, agent yield bridge, event catalogue, research |

→ [Full tutorials index](https://oracle-samples.github.io/locus/tutorials/)

---

## Workbench

Try every tutorial in your browser. Bring your own model key — no install required.

```bash
# or open in GitHub Codespaces (badge above)
cd workbench && docker-compose up
```

Three model slots (A / B / C) so multi-agent tutorials can mix a fast triage model with a deeper specialist. Tutorials tab, Skills tab, Protocols tab (shows all eight cognitive router protocols with cost + latency metadata).

→ [Workbench guide](docs/workbench.md)

---

## Deploy

```bash
pip install "locus-sdk[oci,server]"
```

`AgentServer` is a drop-in FastAPI app: `POST /invoke`, `POST /stream`, `GET/DELETE /threads/{id}`, `GET /health`.

```python
from locus.server import AgentServer

server = AgentServer(agent=my_agent, api_key=os.environ["API_KEY"])
server.run(host="0.0.0.0", port=8080)
```

The repo ships a multi-stage `Dockerfile` and a Helm chart at
[`deploy/helm/locus-agent/`](deploy/helm/locus-agent/) — Deployment, HPA, Ingress, OCI workload-identity hooks.

→ [Deploy guide](https://oracle-samples.github.io/locus/tutorials/deploy/)

---

## Repo layout

```text
src/locus/
├── agent/          Agent runtime, config, SequentialPipeline / ParallelPipeline / LoopAgent
├── core/           AgentState, Message, events, termination algebra, Send
├── loop/           ReAct nodes (Think, Execute, Reflect)
├── router/         Cognitive router — GoalFrame, ProtocolRegistry, PolicyGate, CognitiveCompiler
├── deepagent/      create_deepagent + create_research_workflow + 6 node primitives
├── observability/  EventBus, run_context, agent yield bridge, EV_* constants
├── memory/         BaseCheckpointer + 9 backends
├── models/         Provider registry + OCI, OpenAI, Anthropic, Ollama
├── multiagent/     Orchestrator, Swarm, Handoff, StateGraph, Functional
├── a2a/            Cross-process Agent-to-Agent protocol
├── reasoning/      Reflexion, Grounding, Causal, GSAR
├── rag/            Embeddings + 7 vector stores + retrievers
├── providers/      Multi-modal: web search, web fetch, image, speech
├── tools/          @tool decorator, registry, builtins, executors
├── hooks/          Logging, telemetry, retry, guardrails, steering
├── skills/         AgentSkills.io filesystem-first capability disclosure
├── playbooks/      Declarative step plans + PlaybookEnforcer
├── server/         FastAPI AgentServer with thread persistence
├── evaluation/     EvalCase + EvalRunner + EvalReport
└── integrations/   MCP (client + server)

workbench/          Browser playground — Tutorials / Skills / Protocols tabs,
                    three model slots, SSE event stream, Codespaces-ready.
examples/           56 progressive tutorials, each a single runnable file.
tests/unit/         Deterministic, no external deps. Runs in CI on every PR.
tests/integration/  Live OCI / OpenAI / Oracle Database 26ai. Gated on credentials.
```

---

## Contributing

```bash
git clone https://github.com/oracle-samples/locus.git
cd locus && pip install -e ".[dev,all]"
hatch run check        # ruff + mypy
hatch run test         # unit tests across Python 3.11–3.14
pre-commit install
```

See [CONTRIBUTING.md](CONTRIBUTING.md). Every PR runs format, lint, mypy, unit tests, DCO sign-off.

---

## Citing GSAR

```bibtex
@article{kamelhar2026gsar,
  title   = {GSAR: Typed Grounding for Hallucination Detection and Recovery in Multi-Agent LLMs},
  author  = {Kamelhar, Federico A.},
  journal = {arXiv preprint arXiv:2604.23366},
  year    = {2026},
}
```

---

## Security

Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process.

---

## License

Copyright (c) 2026 Oracle and/or its affiliates.

Released under the Universal Permissive License v1.0 as shown at
<https://oss.oracle.com/licenses/upl/>.
