Documentation Index Fetch the complete documentation index at: https://docs.praison.ai/llms.txt
Use this file to discover all available pages before exploring further.
Tasks are the core unit of work in the A2A protocol, managing the complete lifecycle from submission to completion with built-in state tracking and storage.
Quick Start
Send Message (Creates Task)
import aiohttp
import json
async def send_message ():
payload = {
" jsonrpc " : " 2.0 " ,
" method " : " message/send " ,
" id " : " 1 " ,
" params " : {
" message " : {
" role " : " user " ,
" parts " : [{ " text " : " Analyze this data " }]
}
}
}
async with aiohttp . ClientSession () as session :
async with session . post ( " http://localhost:8000/a2a " , json = payload ) as response :
result = await response . json ()
task_id = result [ " result " ][ " id " ]
print ( f "Task created: { task_id } " )
Get Task Status
async def get_task_status ( task_id ):
payload = {
" jsonrpc " : " 2.0 " ,
" method " : " tasks/get " ,
" id " : " 2 " ,
" params " : { " id " : task_id }
}
async with aiohttp . ClientSession () as session :
async with session . post ( " http://localhost:8000/a2a " , json = payload ) as response :
result = await response . json ()
state = result [ " result " ][ " status " ][ " state " ]
print ( f "Task state: { state } " )
Cancel Task
async def cancel_task ( task_id ):
payload = {
" jsonrpc " : " 2.0 " ,
" method " : " tasks/cancel " ,
" id " : " 3 " ,
" params " : { " id " : task_id }
}
async with aiohttp . ClientSession () as session :
async with session . post ( " http://localhost:8000/a2a " , json = payload ) as response :
result = await response . json ()
print ( f "Cancelled: { result [ ' result ' ][ ' status ' ][ ' state ' ] } " )
Task Lifecycle
Every A2A interaction creates a Task that progresses through defined states:
Task States
State Description submittedTask received, not yet processing workingAgent is actively processing completedTask finished successfully failedTask failed with an error cancelledTask was cancelled by client input_requiredAgent needs more information auth_requiredAuthentication required
Python Task States
from praisonaiagents . ui . a2a import TaskState
print ( TaskState . SUBMITTED . value ) # "submitted"
print ( TaskState . WORKING . value ) # "working"
print ( TaskState . COMPLETED . value ) # "completed"
print ( TaskState . FAILED . value ) # "failed"
print ( TaskState . CANCELLED . value ) # "cancelled"
print ( TaskState . INPUT_REQUIRED . value ) # "input_required"
print ( TaskState . AUTH_REQUIRED . value ) # "auth_required"
Task Structure
A task contains all information about an A2A interaction:
from praisonaiagents . ui . a2a import Task , TaskStatus , TaskState , Message , Artifact
task = Task (
id = " task-uuid-123 " ,
context_id = " ctx-uuid-456 " ,
status = TaskStatus ( state = TaskState . COMPLETED ),
history =[
Message ( role = " user " , parts =[ TextPart ( text = " Hello " )]),
Message ( role = " agent " , parts =[ TextPart ( text = " Hi there! " )]),
],
artifacts =[
Artifact (
artifact_id = " art-001 " ,
parts =[ TextPart ( text = " Response content " )],
)
],
)
Task Fields
Field Type Description idstrUnique task ID (auto-generated UUID) context_idstrConversation context ID statusTaskStatusCurrent state + optional message historyList[Message]Message exchange history artifactsList[Artifact]Output artifacts from agent
JSON-RPC Methods
tasks/get — Retrieve a Task
curl -X POST http://localhost:8000/a2a \
-H " Content-Type: application/json " \
-d ' {
"jsonrpc": "2.0",
"method": "tasks/get",
"id": "1",
"params": {
"id": "task-uuid-123"
}
} '
Response:
{
" jsonrpc " : " 2.0 " ,
" id " : " 1 " ,
" result " : {
" id " : " task-uuid-123 " ,
" contextId " : " ctx-uuid-456 " ,
" status " : { " state " : " completed " },
" history " : [
{ " role " : " user " , " parts " : [{ " text " : " Hello " }]},
{ " role " : " agent " , " parts " : [{ " text " : " Hi there! " }]}
],
" artifacts " : [
{ " artifactId " : " art-001 " , " parts " : [{ " text " : " Response " }]}
]
}
}
Task not found:
{
" jsonrpc " : " 2.0 " ,
" id " : " 1 " ,
" error " : { " code " : -32000 , " message " : " Task not found: task-uuid-123 " }
}
tasks/list — List Tasks
The tasks/list method is available in the task store but not yet exposed via JSON-RPC. This method is planned for future implementation.
The task store supports listing tasks with optional context filtering:
# From the task store (server-side only)
from praisonaiagents . ui . a2a . task_store import TaskStore
store = TaskStore ()
# List all tasks
all_tasks = store . list_tasks ()
# Filter by context
context_tasks = store . list_tasks ( context_id = " ctx-uuid-456 " )
Planned JSON-RPC Interface:
# Future implementation
curl -X POST http://localhost:8000/a2a \
-H " Content-Type: application/json " \
-d ' {
"jsonrpc": "2.0",
"method": "tasks/list",
"id": "1",
"params": {
"contextId": "ctx-uuid-456"
}
} '
tasks/cancel — Cancel a Task
curl -X POST http://localhost:8000/a2a \
-H " Content-Type: application/json " \
-d ' {
"jsonrpc": "2.0",
"method": "tasks/cancel",
"id": "1",
"params": {
"id": "task-uuid-123"
}
} '
Response:
{
" jsonrpc " : " 2.0 " ,
" id " : " 1 " ,
" result " : {
" id " : " task-uuid-123 " ,
" status " : { " state " : " cancelled " }
}
}
Python Client Implementation
A high-level A2AClient class is planned for future releases. Currently, use direct HTTP calls with aiohttp or requests.
import aiohttp
import json
class SimpleA2AClient :
def __init__ ( self , base_url : str ):
self . base_url = base_url . rstrip ( ' / ' ) + ' /a2a '
async def send_message ( self , text : str , context_id : str = None ):
payload = {
" jsonrpc " : " 2.0 " ,
" method " : " message/send " ,
" id " : " 1 " ,
" params " : {
" message " : {
" role " : " user " ,
" parts " : [{ " text " : text }],
" contextId " : context_id
}
}
}
async with aiohttp . ClientSession () as session :
async with session . post ( self . base_url , json = payload ) as response :
return await response . json ()
async def get_task ( self , task_id : str ):
payload = {
" jsonrpc " : " 2.0 " ,
" method " : " tasks/get " ,
" id " : " 2 " ,
" params " : { " id " : task_id }
}
async with aiohttp . ClientSession () as session :
async with session . post ( self . base_url , json = payload ) as response :
return await response . json ()
async def cancel_task ( self , task_id : str ):
payload = {
" jsonrpc " : " 2.0 " ,
" method " : " tasks/cancel " ,
" id " : " 3 " ,
" params " : { " id " : task_id }
}
async with aiohttp . ClientSession () as session :
async with session . post ( self . base_url , json = payload ) as response :
return await response . json ()
# Usage
async def main ():
client = SimpleA2AClient ( " http://localhost:8000 " )
# Send a message (creates a task)
result = await client . send_message ( " Analyze this data " )
task_id = result [ " result " ][ " id " ]
context_id = result [ " result " ][ " contextId " ]
# Get task status
task = await client . get_task ( task_id )
print ( f "State: { task [ ' result ' ][ ' status ' ][ ' state ' ] } " )
# Cancel a task
cancelled = await client . cancel_task ( task_id )
print ( f "Cancelled: { cancelled [ ' result ' ][ ' status ' ][ ' state ' ] } " )
Task Store
The A2A server maintains an in-memory task store that tracks all tasks:
Tasks are automatically created when message/send or message/stream is called
Each task gets a unique UUID
Tasks within the same conversation share a contextId
Task history includes both user messages and agent responses
Artifacts contain the agent’s output
Store is per-server-instance and does not persist across restarts
Context-Based Conversations
Tasks can be grouped by contextId for multi-turn conversations:
client = SimpleA2AClient ( " http://localhost:8000 " )
# First message — new context created
r1 = await client . send_message ( " What is Python? " )
ctx = r1 [ " result " ][ " contextId " ]
# Follow-up — same context
r2 = await client . send_message ( " What about its GIL? " , context_id = ctx )
# Both tasks now share the same contextId for conversation tracking
print ( f "Context ID: { ctx } " )
print ( f "First task: { r1 [ ' result ' ][ ' id ' ] } " )
print ( f "Second task: { r2 [ ' result ' ][ ' id ' ] } " )
Error Handling
Common error codes returned by task management methods:
Error Code Message When -32602Invalid params: ‘id’ required Missing task ID -32000Task not found Task ID doesn’t exist -32601Method not found Unknown JSON-RPC method
Error Response Format:
{
" jsonrpc " : " 2.0 " ,
" id " : " 1 " ,
" error " : {
" code " : -32000 ,
" message " : " Task not found: task-uuid-123 "
}
}
Best Practices
Always check task state before assuming completion. Tasks can fail or require input. client = SimpleA2AClient ( " http://localhost:8000 " )
task = await client . get_task ( task_id )
state = task [ " result " ][ " status " ][ " state " ]
if state == " completed " :
# Process results
elif state == " failed " :
# Handle error
elif state == " input_required " :
# Provide additional input
Use context IDs to group related tasks and maintain conversation history. # Keep context for follow-up questions
result = await client . send_message ( " Initial question " )
context_id = result [ " result " ][ " contextId " ]
follow_up = await client . send_message ( " Follow-up question " , context_id = context_id )
Cancel unnecessary tasks to free resources and avoid confusion. # Cancel long-running tasks when no longer needed
await client . cancel_task ( task_id )
Handle JSON-RPC errors and HTTP errors gracefully. async def safe_send_message ( client , text ):
try :
response = await client . send_message ( text )
if " error " in response :
print ( f "A2A Error: { response [ ' error ' ][ ' message ' ] } " )
return response
except aiohttp . ClientError as e :
print ( f "HTTP Error: { e } " )
return None
A2A Protocol Server setup and configuration
Handoffs Multi-agent communication patterns