Metadata-Version: 2.4
Name: langchain-remote-a2a-agent
Version: 0.2.1
Summary: LangChain-native equivalent of Google ADK's RemoteA2aAgent — invoke remote A2A agents as LangChain Runnables and tools
Project-URL: Homepage, https://github.com/SatyaHimavanth/langchain-remote-a2a-agent
Project-URL: Repository, https://github.com/SatyaHimavanth/langchain-remote-a2a-agent
Project-URL: Issues, https://github.com/SatyaHimavanth/langchain-remote-a2a-agent/issues
Author: Satya Himavanth
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: a2a,agent,agent-to-agent,langchain,llm,multi-agent
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
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: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: a2a-sdk>=1.1.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: langchain-core>=1.4.8
Requires-Dist: langchain>=1.3.11
Requires-Dist: pydantic>=2.0
Description-Content-Type: text/markdown

# langchain-remote-a2a-agent

[![PyPI](https://img.shields.io/pypi/v/langchain-remote-a2a-agent)](https://pypi.org/project/langchain-remote-a2a-agent/)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](pyproject.toml)

LangChain-native equivalent of Google ADK's `RemoteA2aAgent`. Wraps any
[Agent2Agent (A2A)](https://a2a-protocol.org/) protocol server as a
LangChain [`Runnable`](https://python.langchain.com/docs/concepts/runnables/),
so a remote agent can be `.invoke()`d, `.astream()`ed, dropped into a
`create_agent`/LangGraph pipeline as a node, or exposed to another agent
as a callable tool via `.as_tool()` — the same interface you'd use for any
local LangChain component.

This is useful when the agent doing the actual work runs as a separate
service (different language, different team, different deployment) and you
want to compose it into a LangChain-orchestrated system without hand-rolling
the A2A JSON-RPC/SSE client plumbing yourself.

## Install

```bash
pip install langchain-remote-a2a-agent
```

Requires Python 3.11+. Ships a `py.typed` marker — type checkers (mypy,
Pyright) and IDE autocomplete/hover (VS Code + Pylance) pick up the inline
type hints and docstrings automatically once installed.

## Quickstart

```python
from langchain_remote_a2a_agent import RemoteAgent

research = RemoteAgent(
    name="research",
    description="Research agent",
    agent_card_url="http://localhost:8001/.well-known/agent-card.json",
)

result = research.invoke("What is the boiling point of nitrogen?")
print(result["messages"][-1].content)
```

## Multi-turn conversations

Pass a `thread_id` to resume the same server-side A2A context across calls:

```python
from langchain_core.runnables import RunnableConfig

config = RunnableConfig(configurable={"thread_id": "user-42"})

result1 = research.invoke("Tell me about black holes.", config)
result2 = research.invoke("How do they emit Hawking radiation?", config)
```

## Streaming

```python
async for chunk in research.astream("Explain quantum entanglement."):
    if chunk.get("messages"):
        msg = chunk["messages"][-1]
        if reasoning := msg.additional_kwargs.get("reasoning_content"):
            print(f"[reasoning] {reasoning}")
        elif msg.content:
            print(msg.content, end="", flush=True)
```

## As a tool inside a LangChain agent

```python
from langchain.agents import create_agent

supervisor = create_agent(
    model="openai:gpt-5",
    tools=[research.as_tool()],
)
```

## More examples

Nine complete, runnable examples — synchronous/async invocation, multi-turn
state, streaming with reasoning traces, `create_agent` integration, LangGraph
node usage, concurrent batching, bearer-token auth, and agent-card inspection
— live in [`langchain_remote_a2a_agent/examples.py`](langchain_remote_a2a_agent/examples.py).
They're also directly importable for reference:

```python
from langchain_remote_a2a_agent import examples
```

## API surface

| Export | What it is |
|---|---|
| `RemoteAgent` | The main `Runnable` — wraps a remote A2A agent. |
| `RemoteAgent.as_tool()` | Returns a `BaseTool` for use inside another agent's tool list. |
| `RemoteAgent.reset_thread()` | Clears the stored `context_id` for a `thread_id`, starting a fresh server-side conversation. |
| `RemoteAgent.thread_state()` | JSON-serialisable snapshot of a thread's tracked state. |
| `RemoteAgent.aget_agent_card()` | Fetch (or return cached) the remote agent's Agent Card. |
| `RemoteAgent.aget_extended_agent_card()` | Fetch the remote agent's Extended Agent Card. |
| `ThreadState`, `ConversationStateStore` | The conversation-state tracking types, exposed for custom store implementations. |
| `RemoteAgentError` and subclasses | `CardResolutionError`, `A2AProtocolError`, `A2ATimeoutError`, `A2AAuthError`, `A2AStreamError`, `InputNormalisationError` — catch these individually or `RemoteAgentError` for all of them. |

## Agent Card Inspection

You can inspect the capabilities, skills, security requirements, and metadata of the remote agent by fetching its Agent Card:

### Public Agent Card

The Public Agent Card is resolved from the agent card URL when the agent is first initialized:

```python
# Fetch (or return cached) the public agent card
card = await research.aget_agent_card()

print("Agent name:", card.name)
print("Description:", card.description)
print("Skills:", card.skills)
```

### Extended Agent Card

If the remote agent supports an extended card (carrying additional metadata or developer-defined parameters that might require auth/permissions), you can fetch it using `aget_extended_agent_card()`:

```python
# Fetch the extended agent card from the remote server
extended_card = await research.aget_extended_agent_card()

print("Developer info:", extended_card.provider.organization)
print("Extended capabilities:", extended_card.capabilities)
```

## License

Apache License 2.0 — see [LICENSE](LICENSE).