Agent 2 Agent Protocol (A2AP) – Full Technical Report
Version: 1.0 (Production-ready implementation)
Purpose: Structured, reliable, observable, and hierarchical communication between autonomous AI agents in a dynamic swarm.
GitHub: https://github.com/OzzieAI-AU/A2AP
1. What is A2AP?
A2AP is a message-based protocol specifically designed for agent-to-agent coordination.
It goes far beyond simple chat-style messaging by enforcing:
- Typed messages with clear semantics
- Task planning, assignment, tracking, and finalization
- Hierarchical roles (Boss → Manager → Workers)
- Full auditability and state tracking via SwarmState
- Quality gates and revision loops
- Clean completion signaling
It is the nervous system of the OzzieAI Agentica swarm.
2. Core Design Principles
- Everything is a typed message — no raw strings between agents.
- Manager owns the truth — The Manager maintains the live SwarmState.
- Boss only receives final results — It does not micro-manage.
- Workers are specialists — They execute one focused task at a time.
- Completion is explicit — Not guessed via timeouts or counters alone.
- Fully JSON-serializable — Easy to persist, log, or send over any transport.
3. Key Data Structures
SwarmDeploymentPlan
The blueprint generated by the Boss LLM. It defines:
- Manager name and directive
- List of Workers with their worker_name, system_prompt, tools, and collaborators
- Swarm-wide metadata (swarm_id, original_task, timeout, etc.)
Agent Roles
- Boss — Strategic orchestrator. Generates the deployment plan and receives the final report.
- Manager — Tactical coordinator. Breaks down work, assigns tasks, reviews quality, and decides when the mission is complete.
- Worker — Leaf-level executor. Performs the actual reasoning and tool usage.
4. Message Types (The Heart of A2AP)
All communication happens through these strongly-typed messages:
Message Type Direction Purpose SwarmDeployment Boss → Manager Sends the full SwarmDeploymentPlan to start the mission TaskAssignment Manager → Worker (or sub-manager) Assigns one or more TaskDefinitions ResultSubmission Worker → Manager → Boss Submits final output of a task after quality gate ProgressUpdate Any → Manager Real-time progress (optional, not heavily used yet) FinalReport Manager → Boss Official mission complete signal — contains all results Error Any → Manager/Boss Reports failures for graceful handling
All messages inherit from A2APMessage (with message_id, timestamp, sender_agent, recipient_agent, swarm_id, correlation_id).
5. How A2AP Execution Flow Works (Step by Step)
- User gives mission to Boss
Boss receives high-level natural language task. - Boss generates SwarmDeploymentPlan
Uses LLM to intelligently design Manager name + list of specialized Workers. Creates unique swarm_id. - Boss sends SwarmDeploymentMessage to Manager
This is the official hand-off. The swarm now begins. - Manager receives SwarmDeployment
Parses the plan. Creates TaskDefinition for each Worker (injects full context). Sends TaskAssignmentMessage to each Worker (matched by name). - Each Worker executes
Receives TaskAssignmentMessage. Runs Think → Act (tools) → Observe cycle. Aggregates outputs. Sends ResultSubmissionMessage back to Manager. - Manager reviews every result
Runs quality gate. If approved → forwards to Boss. If rejected → sends revision. Updates SwarmState. - Manager declares completion
When all tasks have status Completed, Manager sends FinalReportMessage to Boss. - Boss receives FinalReport
Triggers professional HTML report generation. Mission officially ends.
6. SwarmState & Tracking
The ManagerAgent maintains a live SwarmState object that contains:
- swarm_id
- List of all TaskDefinitions with current status
- Overall status
- Timestamps and metrics
This is the single source of truth for “are we done yet?”
7. Completion Logic (How Boss Knows Everything is Finalised)
The Manager is responsible for deciding completion. Once all tasks are Completed, the Manager sends one FinalReportMessage. The Boss reacts to the FinalReportMessage. This makes the protocol robust and observable.
8. Error Handling
Any agent can send an ErrorMessage. The Manager forwards critical errors to the Boss. Workers that fail repeatedly after revisions are flagged.
9. Why A2AP is Powerful
- Clear separation of concerns: Boss = strategy, Manager = coordination, Worker = execution.
- Quality control built-in: Manager acts as a strict reviewer.
- Full traceability: Every task has ID, status, result, and audit trail.
- Extensible: Easy to add new message types or peer-to-peer collaboration.
- Transport agnostic: Currently uses in-memory AgentBus, but can run over any transport.
10. Current Implementation Status
Full message types and serialization implemented.
Boss → Manager → Worker hierarchy working.
Dynamic swarm generation via LLM working.
Task distribution by name working.
Quality gate + revision loop active.
FinalReport signaling working.
Professional HTML report generation at end.
Remaining areas for future enhancement:
- More sophisticated dependency graphs between tasks.
- Real-time ProgressUpdateMessage dashboard.
- Peer-to-peer worker collaboration when permitted.
- Persistent swarm state across restarts.
Code:
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
/// <summary>
/// Defines the type of message exchanged between agents in the Agent 2 Agent Protocol (A2AP).
/// Every communication in the protocol is typed to enforce clear workflows for deployment, planning,
/// tracking, and finalization of swarm-based tasks.
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum MessageType
{
/// <summary>
/// Initiates a complete swarm deployment from the Boss agent.
/// </summary>
SwarmDeployment,
/// <summary>
/// Assigns one or more tasks from the Manager to Workers (or sub-managers).
/// </summary>
TaskAssignment,
/// <summary>
/// Reports real-time progress and status updates from any agent.
/// </summary>
ProgressUpdate,
/// <summary>
/// Submits the final result of a completed task.
/// </summary>
ResultSubmission,
/// <summary>
/// Delivers the aggregated final report of an entire swarm mission.
/// </summary>
FinalReport,
/// <summary>
/// Reports an error or failure condition that requires attention.
/// </summary>
Error
}
/// <summary>
/// Defines the execution status of any task or subtask within an A2AP swarm.
/// Used consistently across planning, tracking, and finalization phases.
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum TaskStatus
{
/// <summary>
/// Task has been created but not yet started.
/// </summary>
Pending,
/// <summary>
/// Task is actively being executed.
/// </summary>
InProgress,
/// <summary>
/// Task completed successfully.
/// </summary>
Completed,
/// <summary>
/// Task failed and cannot continue without intervention.
/// </summary>
Failed,
/// <summary>
/// Task was explicitly cancelled by the Manager or Boss.
/// </summary>
Cancelled
}
/// <summary>
/// Defines the hierarchical role an agent plays within a specific A2AP swarm deployment.
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum AgentRole
{
/// <summary>
/// Top-level orchestrator that generates the SwarmDeploymentPlan.
/// </summary>
Boss,
/// <summary>
/// Mid-level coordinator that receives the deployment plan, breaks down tasks,
/// assigns work to Workers, tracks progress, and produces the final report.
/// </summary>
Manager,
/// <summary>
/// Leaf-level specialist that executes assigned subtasks using its dedicated system prompt.
/// </summary>
Worker
}
/// <summary>
/// Abstract base class for every message in the Agent 2 Agent Protocol (A2AP).
/// Provides standardized routing, correlation, and auditing fields so that any transport
/// (HTTP, message queues, WebSockets, etc.) can reliably deliver and track communications.
/// All concrete message types inherit from this class and set their specific MessageType.
/// </summary>
public abstract class A2APMessage
{
/// <summary>
/// Globally unique identifier for this individual message (GUID string).
/// </summary>
[JsonPropertyName("message_id")]
public string MessageId { get; set; } = Guid.NewGuid().ToString();
/// <summary>
/// UTC timestamp when the message was created by the sender.
/// </summary>
[JsonPropertyName("timestamp")]
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
/// <summary>
/// Name or identifier of the agent that sent this message.
/// </summary>
[JsonPropertyName("sender_agent")]
public string SenderAgent { get; set; } = string.Empty;
/// <summary>
/// Name or identifier of the intended recipient agent.
/// Use "*" to indicate a broadcast within the swarm.
/// </summary>
[JsonPropertyName("recipient_agent")]
public string RecipientAgent { get; set; } = string.Empty;
/// <summary>
/// The A2AP message type that determines how the recipient should process the payload.
/// </summary>
[JsonPropertyName("message_type")]
public MessageType MessageType { get; set; }
/// <summary>
/// Correlation identifier that links related messages (e.g., a task assignment with its
/// subsequent progress updates and final result). Usually set to the SwarmId or a task-specific ID.
/// </summary>
[JsonPropertyName("correlation_id")]
public string CorrelationId { get; set; } = string.Empty;
/// <summary>
/// Unique identifier of the swarm deployment session to which this message belongs.
/// All agents participating in the same mission share this ID for context.
/// </summary>
[JsonPropertyName("swarm_id")]
public string SwarmId { get; set; } = string.Empty;
}
/// <summary>
/// Represents the complete dynamic swarm hierarchy generated by the Boss LLM.
/// This is the foundational data structure of A2AP and is embedded inside a SwarmDeploymentMessage.
/// The Manager uses this plan to instantiate itself and all required Worker agents.
/// </summary>
public class SwarmDeploymentPlan
{
/// <summary>
/// The name of the Manager agent that will orchestrate the entire swarm.
/// </summary>
[JsonPropertyName("manager_name")]
public string ManagerName { get; set; } = string.Empty;
/// <summary>
/// The high-level directive provided to the Manager describing the overall mission goals,
/// success criteria, and coordination strategy.
/// </summary>
[JsonPropertyName("manager_directive")]
public string ManagerDirective { get; set; } = string.Empty;
/// <summary>
/// The ordered list of specialized Worker agents that the Manager will instantiate and assign subtasks to.
/// Each Worker is purpose-built for a specific aspect of the mission.
/// </summary>
[JsonPropertyName("workers")]
public List<WorkerDeploymentPlan> Workers { get; set; } = new();
/// <summary>
/// The original natural-language task description that the Boss received and used to generate this plan.
/// Retained for full auditability and context.
/// </summary>
[JsonPropertyName("original_task")]
public string OriginalTask { get; set; } = string.Empty;
/// <summary>
/// Unique identifier for the entire swarm deployment session. Generated once by the Boss
/// and propagated to every message and agent involved in the mission.
/// </summary>
[JsonPropertyName("swarm_id")]
public string SwarmId { get; set; } = string.Empty;
/// <summary>
/// Optional maximum allowed execution time (in minutes) for the entire swarm.
/// The Manager may enforce this timeout during tracking.
/// </summary>
[JsonPropertyName("max_execution_minutes")]
public int MaxExecutionMinutes { get; set; } = 60;
}
/// <summary>
/// Represents a single specialized Worker agent that the Manager will dynamically instantiate.
/// Each Worker receives its own tailored system prompt and tool set.
/// </summary>
public class WorkerDeploymentPlan
{
/// <summary>
/// Unique name of this Worker within the swarm (must be unique across all Workers).
/// </summary>
[JsonPropertyName("worker_name")]
public string WorkerName { get; set; } = string.Empty;
/// <summary>
/// Complete system prompt that defines the Worker's persona, expertise, constraints,
/// output format requirements, and any safety or reasoning guidelines.
/// This prompt is used verbatim when spinning up the Worker LLM instance.
/// </summary>
[JsonPropertyName("system_prompt")]
public string SystemPrompt { get; set; } = string.Empty;
/// <summary>
/// List of tool names (or capability identifiers) that this Worker is permitted to invoke.
/// Examples: "web_search", "code_execution", "image_analysis", etc.
/// The hosting runtime interprets these strings to grant the appropriate tools.
/// </summary>
[JsonPropertyName("tools")]
public List<string> Tools { get; set; } = new();
/// <summary>
/// Optional list of other Worker names that this Worker may collaborate with directly.
/// Enables peer-to-peer communication within the swarm when the Manager permits it.
/// </summary>
[JsonPropertyName("collaborators")]
public List<string> Collaborators { get; set; } = new();
}
/// <summary>
/// Message sent by the Boss agent to the designated Manager to deploy an entire swarm.
/// Contains the full SwarmDeploymentPlan that the Manager must execute.
/// This is the entry point of every A2AP mission.
/// </summary>
public class SwarmDeploymentMessage : A2APMessage
{
/// <summary>
/// The complete swarm deployment plan generated by the Boss.
/// </summary>
[JsonPropertyName("deployment_plan")]
public SwarmDeploymentPlan DeploymentPlan { get; set; } = new();
/// <summary>
/// Initializes a new SwarmDeploymentMessage with the correct message type.
/// </summary>
public SwarmDeploymentMessage()
{
MessageType = MessageType.SwarmDeployment;
}
}
/// <summary>
/// Defines a single atomic task or subtask that participates in the swarm's overall mission.
/// Used during planning (by the Manager) and tracking (by all agents).
/// </summary>
public class TaskDefinition
{
/// <summary>
/// Unique identifier for this task within the swarm (usually a short GUID or incremental ID).
/// </summary>
[JsonPropertyName("task_id")]
public string TaskId { get; set; } = string.Empty;
/// <summary>
/// Human-readable title that summarizes the task's purpose.
/// </summary>
[JsonPropertyName("title")]
public string Title { get; set; } = string.Empty;
/// <summary>
/// Detailed description and exact instructions that the assigned agent must follow.
/// </summary>
[JsonPropertyName("description")]
public string Description { get; set; } = string.Empty;
/// <summary>
/// Name of the agent (Worker or sub-Manager) responsible for executing this task.
/// </summary>
[JsonPropertyName("assigned_to")]
public string AssignedTo { get; set; } = string.Empty;
/// <summary>
/// Current execution status of the task.
/// </summary>
[JsonPropertyName("status")]
public TaskStatus Status { get; set; } = TaskStatus.Pending;
/// <summary>
/// List of TaskIds that must be Completed before this task may begin.
/// Enables dependency-driven planning and execution ordering.
/// </summary>
[JsonPropertyName("dependencies")]
public List<string> Dependencies { get; set; } = new();
/// <summary>
/// Priority level (higher number = higher priority). Used by the Manager for scheduling.
/// </summary>
[JsonPropertyName("priority")]
public int Priority { get; set; } = 1;
/// <summary>
/// Optional estimated completion time in minutes.
/// </summary>
[JsonPropertyName("estimated_minutes")]
public int EstimatedMinutes { get; set; } = 0;
}
/// <summary>
/// Message sent by the Manager to one or more Workers (or sub-managers) to assign tasks.
/// This message drives the planning and delegation phase of A2AP.
/// </summary>
public class TaskAssignmentMessage : A2APMessage
{
/// <summary>
/// The complete list of tasks being assigned in this batch.
/// </summary>
[JsonPropertyName("tasks")]
public List<TaskDefinition> Tasks { get; set; } = new();
/// <summary>
/// Initializes a new TaskAssignmentMessage with the correct message type.
/// </summary>
public TaskAssignmentMessage()
{
MessageType = MessageType.TaskAssignment;
}
}
/// <summary>
/// Message sent periodically or on significant events by Workers (or the Manager) to report progress.
/// Enables continuous tracking and allows the Manager to intervene if necessary.
/// </summary>
public class ProgressUpdateMessage : A2APMessage
{
/// <summary>
/// The TaskId this progress update refers to.
/// </summary>
[JsonPropertyName("task_id")]
public string TaskId { get; set; } = string.Empty;
/// <summary>
/// Latest known status of the referenced task.
/// </summary>
[JsonPropertyName("status")]
public TaskStatus Status { get; set; }
/// <summary>
/// Numeric progress percentage (0-100).
/// </summary>
[JsonPropertyName("progress_percentage")]
public int ProgressPercentage { get; set; }
/// <summary>
/// Free-form textual description of what has been accomplished and any blockers encountered.
/// </summary>
[JsonPropertyName("progress_description")]
public string ProgressDescription { get; set; } = string.Empty;
/// <summary>
/// Arbitrary key-value metrics collected during execution (e.g., "tokens_used": "1243", "iterations": "7").
/// </summary>
[JsonPropertyName("metrics")]
public Dictionary<string, string> Metrics { get; set; } = new();
/// <summary>
/// Initializes a new ProgressUpdateMessage with the correct message type.
/// </summary>
public ProgressUpdateMessage()
{
MessageType = MessageType.ProgressUpdate;
}
}
/// <summary>
/// Message sent by a Worker (or sub-manager) to the Manager when a task reaches completion.
/// Contains the final output and any supporting artifacts.
/// </summary>
public class ResultSubmissionMessage : A2APMessage
{
/// <summary>
/// The TaskId of the completed task.
/// </summary>
[JsonPropertyName("task_id")]
public string TaskId { get; set; } = string.Empty;
/// <summary>
/// Primary textual result or answer produced by the task.
/// </summary>
[JsonPropertyName("result")]
public string Result { get; set; } = string.Empty;
/// <summary>
/// Optional structured data payload (JSON-serializable dictionary) for machine-readable results.
/// </summary>
[JsonPropertyName("structured_data")]
public Dictionary<string, object> StructuredData { get; set; } = new();
/// <summary>
/// List of artifact references (e.g., file paths, URLs, or base64-encoded data) produced by the task.
/// </summary>
[JsonPropertyName("artifacts")]
public List<string> Artifacts { get; set; } = new();
/// <summary>
/// Final status of the task upon submission (normally Completed, but may be Failed).
/// </summary>
[JsonPropertyName("final_status")]
public TaskStatus FinalStatus { get; set; } = TaskStatus.Completed;
/// <summary>
/// Initializes a new ResultSubmissionMessage with the correct message type.
/// </summary>
public ResultSubmissionMessage()
{
MessageType = MessageType.ResultSubmission;
}
}
/// <summary>
/// Final message sent by the Manager to the Boss once every task has been completed or the swarm
/// has reached a terminal state. This message finalizes the entire mission and provides a consolidated outcome.
/// </summary>
public class FinalReportMessage : A2APMessage
{
/// <summary>
/// High-level textual summary of the entire swarm mission outcome.
/// </summary>
[JsonPropertyName("summary")]
public string Summary { get; set; } = string.Empty;
/// <summary>
/// Complete list of every task definition together with its final result and status.
/// </summary>
[JsonPropertyName("task_results")]
public List<TaskDefinition> TaskResults { get; set; } = new();
/// <summary>
/// Overall success status of the entire swarm (Completed if all critical tasks succeeded).
/// </summary>
[JsonPropertyName("overall_status")]
public TaskStatus OverallStatus { get; set; }
/// <summary>
/// Any strategic insights, recommendations, or suggested follow-up actions produced by the Manager.
/// </summary>
[JsonPropertyName("insights")]
public string Insights { get; set; } = string.Empty;
/// <summary>
/// Swarm-wide performance metrics (e.g., total_tokens, total_duration_seconds, cost_estimate).
/// </summary>
[JsonPropertyName("metrics")]
public Dictionary<string, string> Metrics { get; set; } = new();
/// <summary>
/// Initializes a new FinalReportMessage with the correct message type.
/// </summary>
public FinalReportMessage()
{
MessageType = MessageType.FinalReport;
}
}
/// <summary>
/// Message used by any agent to report errors, exceptions, or unexpected conditions.
/// Enables graceful failure handling, retries, or escalation within the A2AP swarm.
/// </summary>
public class Error : A2APMessage
{
/// <summary>
/// Short error code or category (e.g., "TOOL_FAILURE", "PROMPT_REJECTION", "TIMEOUT").
/// </summary>
[JsonPropertyName("error_code")]
public string ErrorCode { get; set; } = string.Empty;
/// <summary>
/// Human-readable description of the error.
/// </summary>
[JsonPropertyName("error_message")]
public string ErrorMessage { get; set; } = string.Empty;
/// <summary>
/// Detailed diagnostic information (stack trace, inner exception, or context).
/// </summary>
[JsonPropertyName("details")]
public string Details { get; set; } = string.Empty;
/// <summary>
/// TaskId of the affected task, if the error is scoped to a specific task.
/// </summary>
[JsonPropertyName("affected_task_id")]
public string AffectedTaskId { get; set; } = string.Empty;
/// <summary>
/// Initializes a new ErrorMessage with the correct message type.
/// </summary>
public Error()
{
MessageType = MessageType.Error;
}
}
/// <summary>
/// Maintainable in-memory (or persisted) representation of the entire swarm's current state.
/// The Manager typically owns this object and updates it in response to incoming ProgressUpdateMessage
/// and ResultSubmissionMessage instances. It is used for real-time tracking and can be serialized
/// for persistence or dashboard visualization.
/// </summary>
public class SwarmState
{
/// <summary>
/// The unique swarm identifier shared by all agents.
/// </summary>
[JsonPropertyName("swarm_id")]
public string SwarmId { get; set; } = string.Empty;
/// <summary>
/// The original high-level task description that started the swarm.
/// </summary>
[JsonPropertyName("original_task")]
public string OriginalTask { get; set; } = string.Empty;
/// <summary>
/// Current overall status of the entire swarm mission.
/// </summary>
[JsonPropertyName("overall_status")]
public TaskStatus OverallStatus { get; set; } = TaskStatus.Pending;
/// <summary>
/// Mapping of Worker name → its current TaskStatus (for quick health overview).
/// </summary>
[JsonPropertyName("worker_statuses")]
public Dictionary<string, TaskStatus> WorkerStatuses { get; set; } = new();
/// <summary>
/// Complete list of all tasks in the swarm, including their definitions, current status, and results.
/// </summary>
[JsonPropertyName("tasks")]
public List<TaskDefinition> Tasks { get; set; } = new();
/// <summary>
/// UTC timestamp when the swarm was first deployed.
/// </summary>
[JsonPropertyName("deployment_time")]
public DateTime DeploymentTime { get; set; } = DateTime.UtcNow;
/// <summary>
/// UTC timestamp of the most recent message or status change.
/// </summary>
[JsonPropertyName("last_activity")]
public DateTime LastActivity { get; set; } = DateTime.UtcNow;
/// <summary>
/// Total elapsed time in seconds since deployment (computed on demand).
/// </summary>
[JsonIgnore]
public double ElapsedSeconds => (DateTime.UtcNow - DeploymentTime).TotalSeconds;
}
Summary
A2AP turns a loose collection of LLM agents into a disciplined, hierarchical, auditable swarm.
It works like this:
Boss designs the team → Manager assigns work and enforces quality → Workers execute → Manager verifies everything → Manager tells Boss “mission complete” → Boss delivers final report.
This protocol allows the OzzieAI Agentica framework to reliably tackle complex missions — including heavy binary model analysis — in a structured and observable way.
