Skip to content

A2A Examples

This page provides detailed examples of using the Agent-to-Agent (A2A) protocol with Scoras. These examples demonstrate how to create A2A servers, connect to them with clients, and build multi-agent systems using the A2A protocol.

Basic A2A Server Example

This example shows how to create a simple A2A server with an agent:

import asyncio
import json
import uuid
from typing import Dict, Any, List

import scoras as sc
from scoras.a2a import create_agent_skill, create_a2a_server, run_a2a_server

# Define skills for our A2A agent
math_skill = create_agent_skill(
    id="math",
    name="Mathematics",
    description="Perform mathematical calculations and solve problems",
    tags=["math", "calculation", "problem-solving"],
    examples=[
        "Calculate the derivative of f(x) = x^2 + 3x + 2",
        "Solve the equation 2x + 5 = 13"
    ],
    complexity="standard"
)

research_skill = create_agent_skill(
    id="research",
    name="Research",
    description="Find and analyze information on various topics",
    tags=["research", "information", "analysis"],
    examples=[
        "Summarize the latest research on renewable energy",
        "Compare and contrast different machine learning algorithms"
    ],
    complexity="complex"
)

async def main():
    # Create an agent
    agent = sc.Agent(
        model="openai:gpt-4o",
        system_prompt="You are a helpful assistant with expertise in mathematics and research.",
        enable_scoring=True
    )

    # Create an A2A server
    server = create_a2a_server(
        name="ScorasAgent",
        description="A versatile agent with multiple skills powered by Scoras",
        agent=agent,
        skills=[math_skill, research_skill],
        provider={
            "organization": "Scoras Project",
            "url": "https://scoras.example.com"
        },
        capabilities={
            "streaming": True,
            "push_notifications": False,
            "state_transition_history": True
        },
        authentication_schemes=["bearer"],
        enable_scoring=True
    )

    # Print the agent card
    agent_card = server.get_agent_card()
    print("Agent Card:", json.dumps(agent_card.model_dump(), indent=2))

    # Simulate handling a task
    print("\nSimulating handling a task...")
    task_id = str(uuid.uuid4())
    task_data = {
        "id": task_id,
        "messages": [
            {
                "role": "user",
                "parts": [
                    {
                        "type": "text",
                        "text": "Calculate the area of a circle with radius 5 cm."
                    }
                ]
            }
        ]
    }

    # Handle the task
    response = await server.handle_request({
        "jsonrpc": "2.0",
        "method": "tasks/send",
        "params": {
            "task": task_data
        },
        "id": "request1"
    })

    print("Response:", json.dumps(response, indent=2))

    # Get the complexity score
    score = server.get_complexity_score()
    print("\nServer Complexity Score:", json.dumps(score, indent=2))

    # Run the server
    print("\nStarting A2A server on http://0.0.0.0:8001")
    await run_a2a_server(server, host="0.0.0.0", port=8001)

if __name__ == "__main__":
    asyncio.run(main())

A2A Client Example

This example shows how to connect to an A2A server and use its capabilities:

import asyncio
import json
import uuid
from typing import Dict, Any, List

import scoras as sc
from scoras.a2a import A2AClient

async def main():
    # Create an A2A client
    client = A2AClient(
        agent_url="http://localhost:8001",
        enable_scoring=True
    )

    # Get the agent card
    agent_card = await client.get_agent_card()
    print("Agent Card:")
    print(f"  Name: {agent_card.name}")
    print(f"  Description: {agent_card.description}")
    print(f"  Skills: {[skill.name for skill in agent_card.skills]}")

    # Send a task to the agent
    print("\nSending a math task to the agent...")
    math_task = await client.send_task(
        message="Calculate the area of a circle with radius 5 cm."
    )
    print(f"Task ID: {math_task.id}")
    print(f"Task State: {math_task.state}")

    # Wait for the task to complete
    print("\nWaiting for task to complete...")
    math_task = await client.wait_for_task(math_task.id)

    # Print the response
    print("\nTask completed!")
    print(f"Response: {math_task.messages[-1].parts[0].text}")

    # Send a research task
    print("\nSending a research task to the agent...")
    research_task = await client.send_task(
        message="Summarize the key concepts of quantum computing."
    )

    # Wait for the task to complete
    print("\nWaiting for task to complete...")
    research_task = await client.wait_for_task(research_task.id)

    # Print the response
    print("\nTask completed!")
    print(f"Response: {research_task.messages[-1].parts[0].text}")

    # Get the complexity score
    score = client.get_complexity_score()
    print("\nClient Complexity Score:", json.dumps(score, indent=2))

if __name__ == "__main__":
    asyncio.run(main())

A2A Task Management Example

This example demonstrates managing tasks with the A2A protocol:

import asyncio
import json
import uuid
from typing import Dict, Any, List

import scoras as sc
from scoras.a2a import A2AClient

async def main():
    # Create an A2A client
    client = A2AClient(
        agent_url="http://localhost:8001",
        enable_scoring=True
    )

    # Create a new task
    print("Creating a new task...")
    task = await client.send_task(
        message="What is the formula for calculating the area of a circle?"
    )
    print(f"Task created with ID: {task.id}")
    print(f"Initial state: {task.state}")

    # Get the task
    print("\nRetrieving task...")
    retrieved_task = await client.get_task(task.id)
    print(f"Retrieved task state: {retrieved_task.state}")

    # Send a follow-up message
    print("\nSending follow-up message...")
    updated_task = await client.send_message(
        task_id=task.id,
        message="Also, what is the formula for the circumference?"
    )
    print(f"Updated task state: {updated_task.state}")

    # Wait for the task to complete
    print("\nWaiting for task to complete...")
    completed_task = await client.wait_for_task(task.id)
    print(f"Final task state: {completed_task.state}")

    # Print the conversation
    print("\nFull conversation:")
    for message in completed_task.messages:
        role = message.role
        text = message.parts[0].text if message.parts else ""
        print(f"{role}: {text}")

    # Cancel a task (demonstration only)
    print("\nDemonstrating task cancellation...")
    new_task = await client.send_task(
        message="This task will be cancelled."
    )
    print(f"Created task with ID: {new_task.id}")

    cancelled_task = await client.cancel_task(new_task.id)
    print(f"Cancelled task state: {cancelled_task.state}")

if __name__ == "__main__":
    asyncio.run(main())

A2A Agent Adapter Example

This example shows how to adapt a Scoras agent to use A2A agents:

import asyncio
import json

import scoras as sc
from scoras.a2a import A2AAgentAdapter

async def main():
    # Create a Scoras agent
    agent = sc.Agent(
        model="openai:gpt-4o",
        system_prompt="You are a helpful assistant that can coordinate with other agents.",
        enable_scoring=True
    )

    # Create an A2A agent adapter
    adapter = A2AAgentAdapter(
        agent=agent,
        enable_scoring=True
    )

    # Connect to an A2A agent
    print("Connecting to A2A agent...")
    await adapter.connect_to_agent("http://localhost:8001")

    # Get the agent card
    agent_card = adapter.get_agent_card()
    print(f"Connected to agent: {agent_card.name}")
    print(f"Available skills: {[skill.name for skill in agent_card.skills]}")

    # Run the agent with a query that will use the math skill
    print("\nRunning agent with math query...")
    math_response = await adapter.run("I need to calculate the area of a circle with radius 5 cm.")
    print("Response:", math_response)

    # Run the agent with a query that will use the research skill
    print("\nRunning agent with research query...")
    research_response = await adapter.run("Can you summarize the key concepts of quantum computing?")
    print("Response:", research_response)

    # Get the complexity score
    score = adapter.get_complexity_score()
    print("\nAdapter Complexity Score:", json.dumps(score, indent=2))

if __name__ == "__main__":
    asyncio.run(main())

Streaming A2A Example

This example demonstrates streaming responses from an A2A agent:

import asyncio
import json

import scoras as sc
from scoras.a2a import A2AClient

async def main():
    # Create an A2A client
    client = A2AClient(
        agent_url="http://localhost:8001",
        enable_scoring=True
    )

    # Stream a response from the agent
    print("\nStreaming response from agent...")
    task_id = None

    async for chunk in client.stream_task(
        message="Explain the concept of quantum entanglement in simple terms."
    ):
        if task_id is None:
            task_id = chunk.get("task_id")
            print(f"Task ID: {task_id}")

        if "delta" in chunk:
            print(chunk["delta"], end="", flush=True)

    print("\n\nStreaming completed!")

    # Get the final task
    if task_id:
        task = await client.get_task(task_id)
        print(f"\nFinal task state: {task.state}")

if __name__ == "__main__":
    asyncio.run(main())

Multi-Agent System Example

This example demonstrates building a multi-agent system with A2A:

import asyncio
import json
from typing import Dict, Any, List

import scoras as sc
from scoras.a2a import A2AClient, create_a2a_server, create_agent_skill, run_a2a_server

# Note: This example assumes you have multiple A2A agents running on different ports

async def setup_math_agent():
    """Set up and run a math specialist agent."""
    math_skill = create_agent_skill(
        id="math",
        name="Mathematics",
        description="Perform mathematical calculations and solve problems",
        complexity="standard"
    )

    math_agent = sc.Agent(
        model="openai:gpt-4o",
        system_prompt="You are a mathematics expert. You excel at solving math problems and explaining mathematical concepts.",
        enable_scoring=True
    )

    math_server = create_a2a_server(
        name="MathAgent",
        description="A specialized agent for mathematics",
        agent=math_agent,
        skills=[math_skill],
        enable_scoring=True
    )

    # Run in background
    asyncio.create_task(run_a2a_server(math_server, host="0.0.0.0", port=8001))
    return math_server

async def setup_research_agent():
    """Set up and run a research specialist agent."""
    research_skill = create_agent_skill(
        id="research",
        name="Research",
        description="Find and analyze information on various topics",
        complexity="complex"
    )

    research_agent = sc.Agent(
        model="anthropic:claude-3-opus",
        system_prompt="You are a research specialist. You excel at finding and analyzing information on various topics.",
        enable_scoring=True
    )

    research_server = create_a2a_server(
        name="ResearchAgent",
        description="A specialized agent for research",
        agent=research_agent,
        skills=[research_skill],
        enable_scoring=True
    )

    # Run in background
    asyncio.create_task(run_a2a_server(research_server, host="0.0.0.0", port=8002))
    return research_server

async def setup_writing_agent():
    """Set up and run a writing specialist agent."""
    writing_skill = create_agent_skill(
        id="writing",
        name="Writing",
        description="Create and edit written content",
        complexity="standard"
    )

    writing_agent = sc.Agent(
        model="gemini:gemini-pro",
        system_prompt="You are a writing expert. You excel at creating clear, engaging, and well-structured content.",
        enable_scoring=True
    )

    writing_server = create_a2a_server(
        name="WritingAgent",
        description="A specialized agent for writing",
        agent=writing_agent,
        skills=[writing_skill],
        enable_scoring=True
    )

    # Run in background
    asyncio.create_task(run_a2a_server(writing_server, host="0.0.0.0", port=8003))
    return writing_server

async def run_coordinator():
    """Run a coordinator agent that orchestrates the specialist agents."""
    # Set up the specialist agents
    await setup_math_agent()
    await setup_research_agent()
    await setup_writing_agent()

    # Give servers time to start
    await asyncio.sleep(2)

    # Connect to the specialist agents
    math_client = A2AClient(agent_url="http://localhost:8001")
    research_client = A2AClient(agent_url="http://localhost:8002")
    writing_client = A2AClient(agent_url="http://localhost:8003")

    # Create a coordinator agent
    coordinator = sc.Agent(
        model="openai:gpt-4o",
        system_prompt="You are a coordinator agent that delegates tasks to specialist agents and combines their results.",
        enable_scoring=True
    )

    # Process a complex query
    query = "Create a 500-word article about quantum computing, including mathematical explanations of quantum bits and superposition."
    print(f"Processing query: {query}")

    # Step 1: Research quantum computing
    print("\nStep 1: Delegating research task...")
    research_task = await research_client.send_task(
        message="Research quantum computing, focusing on key concepts and recent developments."
    )
    research_task = await research_client.wait_for_task(research_task.id)
    research_result = research_task.messages[-1].parts[0].text
    print("Research completed!")

    # Step 2: Get mathematical explanations
    print("\nStep 2: Delegating math task...")
    math_task = await math_client.send_task(
        message="Explain quantum bits and superposition mathematically. Include relevant equations and concepts."
    )
    math_task = await math_client.wait_for_task(math_task.id)
    math_result = math_task.messages[-1].parts[0].text
    print("Math explanation completed!")

    # Step 3: Write the article
    print("\nStep 3: Delegating writing task...")
    writing_prompt = f"""
    Create a 500-word article about quantum computing based on the following research and mathematical explanations:

    RESEARCH:
    {research_result}

    MATHEMATICAL EXPLANATIONS:
    {math_result}

    The article should be engaging, clear, and accessible to a general audience while still including the mathematical concepts.
    """

    writing_task = await writing_client.send_task(message=writing_prompt)
    writing_task = await writing_client.wait_for_task(writing_task.id)
    final_article = writing_task.messages[-1].parts[0].text
    print("Article writing completed!")

    # Print the final result
    print("\n=== FINAL ARTICLE ===\n")
    print(final_article)

    # Get complexity scores
    math_score = await math_client.get_complexity_score()
    research_score = await research_client.get_complexity_score()
    writing_score = await writing_client.get_complexity_score()

    print("\nComplexity Scores:")
    print(f"Math Agent: {math_score['complexity_rating']} (Score: {math_score['total_score']})")
    print(f"Research Agent: {research_score['complexity_rating']} (Score: {research_score['total_score']})")
    print(f"Writing Agent: {writing_score['complexity_rating']} (Score: {writing_score['total_score']})")

    # Calculate total system complexity
    total_score = math_score['total_score'] + research_score['total_score'] + writing_score['total_score']
    print(f"Total System Complexity Score: {total_score}")

if __name__ == "__main__":
    asyncio.run(run_coordinator())

A2A with Custom Authentication Example

This example demonstrates using custom authentication with A2A:

import asyncio
import json
import uuid
from typing import Dict, Any, List, Optional

import scoras as sc
from scoras.a2a import create_a2a_server, run_a2a_server, A2AClient

# Custom authentication handler
class CustomAuthHandler:
    def __init__(self):
        self.api_keys = {
            "valid-api-key": "user1",
            "another-valid-key": "user2"
        }

    async def authenticate(self, auth_header: Optional[str]) -> Optional[Dict[str, Any]]:
        """Authenticate a request based on the Authorization header."""
        if not auth_header or not auth_header.startswith("Bearer "):
            return None

        api_key = auth_header[7:]  # Remove "Bearer " prefix

        if api_key in self.api_keys:
            # Return user info on successful authentication
            return {
                "user_id": self.api_keys[api_key],
                "authenticated": True
            }

        return None

async def main():
    # Create an agent
    agent = sc.Agent(
        model="openai:gpt-4o",
        system_prompt="You are a helpful assistant.",
        enable_scoring=True
    )

    # Create skills
    math_skill = create_agent_skill(
        id="math",
        name="Mathematics",
        description="Perform mathematical calculations",
        complexity="standard"
    )

    # Create auth handler
    auth_handler = CustomAuthHandler()

    # Create an A2A server with custom authentication
    server = create_a2a_server(
        name="SecureAgent",
        description="A secure agent with custom authentication",
        agent=agent,
        skills=[math_skill],
        authentication_schemes=["bearer"],
        authentication_handler=auth_handler.authenticate,
        enable_scoring=True
    )

    # Run the server in the background
    asyncio.create_task(run_a2a_server(server, host="0.0.0.0", port=8001))

    # Give the server time to start
    await asyncio.sleep(1)

    # Create an A2A client with authentication
    client = A2AClient(
        agent_url="http://localhost:8001",
        auth_token="valid-api-key",
        enable_scoring=True
    )

    # Send a task to the agent
    print("Sending task with valid authentication...")
    try:
        task = await client.send_task(
            message="Calculate the area of a circle with radius 5 cm."
        )
        print(f"Task created with ID: {task.id}")

        # Wait for the task to complete
        completed_task = await client.wait_for_task(task.id)
        print(f"Response: {completed_task.messages[-1].parts[0].text}")
    except Exception as e:
        print(f"Error: {e}")

    # Create a client with invalid authentication
    invalid_client = A2AClient(
        agent_url="http://localhost:8001",
        auth_token="invalid-api-key",
        enable_scoring=True
    )

    # Try to send a task with invalid authentication
    print("\nSending task with invalid authentication...")
    try:
        task = await invalid_client.send_task(
            message="This should fail due to invalid authentication."
        )
        print(f"Task created with ID: {task.id}")
    except Exception as e:
        print(f"Error as expected: {e}")

if __name__ == "__main__":
    asyncio.run(main())

Next Steps