Skip to main content

A2AFlow

A lightweight, framework-agnostic bridge between PocketFlow and the Agent2Agent protocol

License: MIT Documentation

Overview

A2AFlow combines the minimalist approach of PocketFlow with Google's Agent2Agent (A2A) protocol, creating a powerful yet lightweight framework for building interoperable AI agents.

  • Lightweight: Just ~200 lines of core code built on PocketFlow's 100-line foundation
  • Interoperable: Seamlessly connect with any A2A-compatible agent
  • Framework-agnostic: Works with any LLM provider or agent framework
  • Clean abstractions: Simple, intuitive API that follows PocketFlow's design philosophy

Features

  • A2A Protocol Support: Full implementation of the A2A protocol specification
  • Graph-based Processing: Use PocketFlow's intuitive directed graph structure for agent logic
  • Streaming Responses: Real-time updates for longer processing tasks
  • Push Notifications: Server-initiated communication for background processing
  • Multi-modal Content: Support for text, images, structured data, and more
  • Session Management: Built-in state tracking across multiple interactions
  • Tool Integration: Easy integration with external tools and API calls

Installation

# Install UV if you don't have it already
pip install uv

# Install A2AFlow
uv sync

Using Pip

pip install a2aflow

Install from Source

# Clone the repository
git clone https://github.com/your-username/A2AFlow.git
cd A2AFlow

# Using UV (recommended)
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
uv sync --group dev --group docs

# Using Pip
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -e ".[dev,docs]"

Quick Start

Create an A2A-Compatible Agent

from a2aflow import A2ANode, A2AFlow, A2AServer

# 1. Define your agent node
class QuestionAnswerNode(A2ANode):
    def exec(self, query):
        return f"The answer to '{query}' is 42!"

# 2. Create a flow with A2A capabilities
qa_node = QuestionAnswerNode()
flow = A2AFlow(
    start=qa_node,
    capabilities={"streaming": True, "pushNotifications": False},
    skills=[{"id": "qa_skill", "name": "Question answering"}]
)

# 3. Start the A2A server
server = A2AServer(
    flow=flow,
    host="localhost",
    port=10000
)
server.start()

Connect to an A2A Agent

from a2aflow import A2AClient

# Connect to an A2A server
client = A2AClient(url="http://localhost:10000")

# Send a task and get response
response = await client.send_task("What is the meaning of life?")
print(response["result"]["status"]["message"]["parts"][0]["text"])
# Output: The answer to 'What is the meaning of life?' is 42!

More Examples

Streaming Agent

from a2aflow import AsyncA2ANode, A2AFlow, A2AServer
import asyncio

class StreamingNode(AsyncA2ANode):
    async def exec_async(self, query):
        for i in range(5):
            yield f"Processing step {i+1}..."
            await asyncio.sleep(0.5)
        yield f"Final answer: {query} → Completed!"

# Create and start server with streaming capabilities
flow = A2AFlow(start=StreamingNode(), capabilities={"streaming": True})
server = A2AServer(flow, host="localhost", port=10000)
server.start()

Multi-turn Agent with Memory

from a2aflow import A2ANode, A2AFlow, A2AServer

class ConversationNode(A2ANode):
    def prep(self, shared):
        # Initialize conversation history
        if "history" not in shared:
            shared["history"] = []
        
        # Get query and pass history for context
        query = self._get_user_query(shared.get("a2a_request", {}).get("params", {}))
        return {"query": query, "history": shared["history"]}
    
    def exec(self, inputs):
        query, history = inputs["query"], inputs["history"]
        
        # Simple response based on history length
        if not history:
            response = f"Hello! You said: {query}"
        else:
            response = f"You've sent {len(history)+1} messages. Most recent: {query}"
        
        return response
    
    def post(self, shared, prep_res, exec_res):
        # Update conversation history
        shared["history"].append({"query": prep_res["query"], "response": exec_res})
        return "default"

# Create and start conversation agent
flow = A2AFlow(start=ConversationNode())
server = A2AServer(flow, host="localhost", port=10000)
server.start()

Documentation

For more detailed documentation, examples, and tutorials, visit our documentation site.

Design Patterns

A2AFlow supports all the design patterns from PocketFlow:

  • Agent: Build agentic systems that make decisions based on context
  • RAG: Implement Retrieval Augmented Generation for context-aware responses
  • MapReduce: Process large inputs by splitting and then aggregating
  • Multi-Agent: Create collaborative agent systems
  • Workflow: Chain multiple steps for complex tasks

Plus A2A-specific patterns:

  • Agent Discovery: Auto-discover agent capabilities through Agent Cards
  • Multi-modal Conversations: Exchange text, images, and structured data
  • Push-Based Background Processing: Process tasks asynchronously with callbacks

A2A Protocol Support

A2AFlow implements the full A2A protocol specification:

  • Agent Card: Well-known endpoint with agent capabilities
  • Task Management: Create, monitor, and cancel tasks
  • Streaming: Real-time progress updates
  • Push Notifications: Server-initiated callbacks
  • Multi-modal Content: Support for text, files, and structured data

Contributing

We welcome contributions! Please see CONTRIBUTING.md for details on how to get started.

Development Setup

We recommend using UV for development:

# Clone the repository
git clone https://github.com/your-username/A2AFlow.git
cd A2AFlow

# Create and activate a virtual environment
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install dependencies including development and documentation groups
uv sync --group dev --group docs

# Run tests
pytest

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

A2AFlow is built on two amazing projects:

Special thanks to all contributors to both projects.


Built with ❤️ by ClosedLoop and the community

Metadata

Release files for a2aflow 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for a2aflow 0.1.1
File Size Uploaded Provenance Actions
a2aflow-0.1.1.tar.gz 83.3 kB Without provenance Details for a2aflow-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for a2aflow 0.1.1
File Interpreter ABI Platform Actions
a2aflow-0.1.1-py3-none-any.whl Python 3 none any Details for a2aflow-0.1.1-py3-none-any.whl

Total release size: 96.3 kB

Release files / a2aflow-0.1.1.tar.gz

Download URL a2aflow-0.1.1.tar.gz
Size 83.3 kB
Tags Source
SHA-256 checksum
How to use checksums
411fac203a4c2dfc520c3c418568b567b5b9ea361958f0608ef51d707def37e3
BLAKE2b-256 checksum
How to use checksums
eb41367e86d6a6667276e87fa33ae663d2fbd7da7202098d6ea09b4464752078
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Release files / a2aflow-0.1.1-py3-none-any.whl

Download URL a2aflow-0.1.1-py3-none-any.whl
Size 13.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f8175264714ccfb4e88259b00ffed658a031deee20b34ad58d2df6327a3efcb
BLAKE2b-256 checksum
How to use checksums
22436c7a5cf1db6ea85f32a4bedcfd52a9d9f154f43c95959967f652249061a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.9

Security for a2aflow 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page