Metadata-Version: 2.5
Name: babelagent
Version: 0.1.3
Summary: The Babel that lets AI agents understand each other: a neutral layer where heterogeneous agents (callables, HTTP/OpenAPI, MCP, framework agents, LLMs) share one interface, collaborate (A2A), and get graded at each hop.
Author-email: Amit Patole <amit.patole@gmail.com>
License: MIT
License-File: LICENSE
Keywords: a2a,adapters,agents,ai,dag,interoperability,multi-agent,orchestration
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx<1,>=0.27
Requires-Dist: platformdirs<5,>=4.0
Requires-Dist: pydantic-settings<3,>=2.2
Requires-Dist: pydantic<3,>=2.6
Requires-Dist: typer<1,>=0.12
Provides-Extra: agentsensory
Requires-Dist: agentsensory>=0.1; extra == 'agentsensory'
Provides-Extra: all
Requires-Dist: anthropic>=0.40; extra == 'all'
Requires-Dist: fastapi>=0.110; extra == 'all'
Requires-Dist: langchain-core>=0.3; extra == 'all'
Requires-Dist: mcp>=1.2; extra == 'all'
Requires-Dist: ollama>=0.3; extra == 'all'
Requires-Dist: openai>=1.0; extra == 'all'
Requires-Dist: python-multipart>=0.0.9; extra == 'all'
Requires-Dist: uvicorn[standard]>=0.29; extra == 'all'
Provides-Extra: cloud
Requires-Dist: anthropic>=0.40; extra == 'cloud'
Requires-Dist: openai>=1.0; extra == 'cloud'
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Provides-Extra: frameworks
Requires-Dist: langchain-core>=0.3; extra == 'frameworks'
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == 'mcp'
Provides-Extra: ollama
Requires-Dist: ollama>=0.3; extra == 'ollama'
Provides-Extra: serve
Requires-Dist: fastapi>=0.110; extra == 'serve'
Requires-Dist: python-multipart>=0.0.9; extra == 'serve'
Requires-Dist: uvicorn[standard]>=0.29; extra == 'serve'
Description-Content-Type: text/markdown

# Babelagent

[![PyPI](https://img.shields.io/pypi/v/babelagent.svg)](https://pypi.org/project/babelagent/)
[![Docs](https://img.shields.io/badge/docs-live-3f8a86)](https://amitpatole.github.io/babelagent/)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.22129957.svg)](https://doi.org/10.5281/zenodo.22129957)
[![License: MIT](https://img.shields.io/badge/license-MIT-1b1a17)](LICENSE)

> The Babel that lets AI agents understand each other. One shared tongue for agents that were never meant to talk.

Every agent framework has its own idea of what an agent is. LangChain has Runnables with `.invoke`,
CrewAI has Crews with `.kickoff`, AutoGen has agents with `.generate_reply`, an LLM has
`messages.create`, a microservice has an HTTP route. None of them agree on a shape, so connecting any
two means writing glue.

Babelagent is the neutral layer in between. You bring your own agents, whatever they are (a callable,
an HTTP/OpenAPI endpoint, an MCP tool, a framework agent, or an LLM), and it wraps each one in a single
shared interface so they can exchange messages and collaborate on a task, **agent-to-agent (A2A)**.
The value is not any single adapter. It is that once something is adapted, it works with everything
else you have adapted.

The headline is **`adapt()`**: hand Babelagent almost anything and it builds the connector on the fly.

```python
import asyncio
from babelagent import Graph

async def main():
    graph = (
        Graph()
        .node("clean",   str.strip)
        .node("shout",   str.upper)
        .node("exclaim", lambda s: s + "!")
    )
    result = await graph.run("  hello  ")
    print(result.output)   # "HELLO!"

asyncio.run(main())
```

Let different agents work in parallel and hand their results to each other, with barrier policies on
the join:

```python
from babelagent import Graph, adapt

g = Graph()
g.node("src",     lambda text: text)
g.node("summary", adapt(langchain_agent), after=["src"])   # a LangChain agent
g.node("labels",  adapt("https://api.example.com/classify"), after=["src"])  # an HTTP service
# merge receives {"summary": ..., "labels": ...} keyed by node name (>=2 upstreams)
g.join("merge", after=["summary", "labels"], agent=combine, barrier="all")
result = await g.run(document)
```

## Concepts

| Concept | What it is |
|---|---|
| **Graph** | Builds the network of agents (linear chaining **and** a DAG API) |
| **CompiledGraph** | The validated, runnable graph; `await graph.run(payload)` |
| **Node** | One participant: an agent plus an optional quality check/gate |
| **Agent** | The uniform `async run(message, ctx) -> message` interface |
| **`adapt()`** | Turns any brought object into an Agent, inferring the adapter |
| **Message / Result** | The envelope agents exchange / the final output + run trace |
| **Barrier** | Fan-in join policy: `all` · `k_of_n` · `optional` |

## Install

```bash
pip install babelagent                 # light base (callables + HTTP)
pip install "babelagent[mcp]"          # MCP tools
pip install "babelagent[cloud]"        # Anthropic / OpenAI
pip install "babelagent[ollama]"       # local models
pip install "babelagent[frameworks]"   # LangChain (CrewAI/AutoGen detected if installed)
pip install "babelagent[serve]"        # REST service
pip install "babelagent[all]"
```

## Try it (no API key)

```bash
babelagent demo      # a broken agent (gated FAIL) then a fixed one (PASS)
babelagent doctor    # which adapter families are available
babelagent inspect   # print a graph's topology as JSON
```

## Cite

If you use Babelagent, please cite it (concept DOI, always resolves to the latest version):

> Amit Patole. *Babelagent*. https://doi.org/10.5281/zenodo.22129957

A machine-readable `CITATION.cff` is in the repo.

## Status

Alpha, in active development. MIT licensed.

— amitpatole
