back to blog & resources
Blog

Bilgin Ibryam

|

November 24, 2025

Making Agent-to-Agent (A2A) Communication Secure and Reliable with Dapr

The Agent-to-Agent (A2A) protocol enables agents to collaborate but lacks enterprise-grade security and reliability. Dapr bridges this gap with built-in mTLS, OAuth2/OIDC support, access control, secret management, and observability, making A2A secure, resilient, and production-ready across all languages and agent frameworks.

The Agent-to-Agent (A2A) protocol is an open standard that lets autonomous AI agents discover each other, exchange messages, and collaborate across systems. Recently, it was donated by Google to the Linux Foundation, shifting it into a neutral, vendor-agnostic home, which signals that A2A is not just a research toy but aims to become a foundational standard in the multi-agent ecosystem.

Dapr brings enterprise readiness to the A2A protocol

The core problem A2A solves is agent interoperability. It offers a common language for agents to advertise capabilities, invoke each other,  stream events, and coordinate task lifecycles. 

That said, the A2A spec intentionally leaves out key operational concerns. As the specification acknowledges, authentication, authorization, security, privacy, tracing, resiliency, and monitoring must be “aligned with established enterprise practices” but not mandated in the protocol. The spec says you should handle them, but gives no standard or implementation. This is exactly where a production deployment can stumble.

Imagine a Customer Service Agent handling a failed product delivery. It calls a Logistics Agent to fetch shipment data, then a Policy Agent to decide whether a refund or replacement applies.

In production, this simple interaction can fail in several ways:

  • Without secure transport (mTLS), customer and shipment data may leak.
  • Without authentication and authorization, unauthorized agents can impersonate others or access private data.
  • Without resiliency policies (retries, timeouts, circuit breakers), transient errors can break the workflow.
  • Without observability (tracing, metrics, logs), failures are hard to diagnose.
  • Without access control, one misconfigured agent might perform unintended actions.

This post demonstrates how we can fill these A2A  gaps rapidly using Dapr as a drop-in addition for any A2A implementation, regardless of the language or agentic framework.

A2A Requirements and Best Practices

Let’s demonstrate how to make A2A enterprise-ready using one of the official A2A Java sample apps and follow the key recommendations from the A2A Enterprise Ready guide. We’ll go through them one by one and show how Dapr fills each gap cleanly, starting with Transport Layer Security (TLS).

1. Transport Level Security (TLS) Requirements

To ensure the confidentiality and integrity of data in transit, the A2A protocol requires:

  • That all A2A communication in production occurs over HTTPS.
  • The use of modern TLS (1.2 or higher) and strong cipher suites.
  • Verified server identity to prevent man-in-the-middle attacks.

How Dapr Solves This

Dapr provides mutual TLS (mTLS) out of the box through:

  • Certificates and SPIFFE IDs are issued and managed automatically by Sentry service.
  • Certificates can rotate easily with managed trust domains
  • All sidecar-to-sidecar (agent-to-agent) communication is encrypted and authenticated.

Configuring a Dapr Configuration resource demonstrates how easy it is to enable mTLS between agents:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
  namespace: default
spec:
  mtls:
    enabled: true

Once applied, all A2A calls through Dapr sidecars are automatically secured, no manual certificate setup or code changes required.

2. Authentication Requirements

A2A relies on standard web authentication: OAuth2, OpenID Connect (OIDC), API keys, or mTLS, declared in each agent’s Agent Card under the securitySchemes section.
The spec supports multiple schemes:

message SecurityScheme {
  oneof scheme {
    APIKeySecurityScheme api_key_security_scheme = 1;
    HTTPAuthSecurityScheme http_auth_security_scheme = 2;
    OAuth2SecurityScheme oauth2_security_scheme = 3;
    OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4;
    MutualTlsSecurityScheme mtls_security_scheme = 5;
  }
}

Depending on the interaction pattern, this in practice means:

  • User or edge calls → use OIDC/OAuth2 for delegated user authentication.
  • Agent-to-agent callsmTLS (as shown earlier) provides secure, mutual identity

How Dapr Solves This

Dapr natively supports all of these models:

  • OAuth2 / OIDC middleware – Handles token validation automatically using Authorization Code or Client Credentials flows.
  • mTLS – Already enabled between sidecars for secure agent-to-agent communication.
  • App / Dapr API tokens – Provide lightweight static authentication for internal endpoints.

Example (OAuth2 middleware component):

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: oauth2
  namespace: default
spec:
  type: middleware.http.oauth2
  version: v1
  metadata:
  - name: clientId
    value: "<client-id>"
  - name: clientSecret
    value: "<client-secret>"
  - name: authURL
    value: "<authorization-url>"
  - name: tokenURL
    value: "<token-url>"
  - name: scopes
    value: "<comma-separated scopes>"

Attach this middleware to your Dapr sidecar pipeline, and all requests are validated before reaching your A2A agent. For edge traffic, OIDC ensures user identity; for agent-to-agent traffic, Dapr’s built-in mTLS already enforces trust and authentication transparently.

3. Authorization Requirement

Once a client is authenticated, the A2A server must decide what that client is allowed to do. According to the Enterprise Ready guide:

  • Granular control: Authorization should depend on the authenticated identity, user, app, or both.
  • Skill-based access: Use OAuth scopes or similar to limit which skills or endpoints can be invoked.
  • Least privilege: Default to denying access and only allow what’s explicitly needed.

How Dapr Solves This

Dapr provides a simple Access Control List (ACL) mechanism through its configuration file. It enforces authorization at the sidecar level, meaning every inbound call to your agent passes through the ACL before reaching your application code.

Below is an example ACL configuration applied to the A2A server agent:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
  namespace: default
spec:
  mtls:
    enabled: true
  accessControl:
    defaultAction: deny
    trustDomain: "public"
    policies:
      - appId: client
        trustDomain: "public"
        namespace: "default"
        operations:
          - name: /.well-known/agent-card.json
            httpVerb: ["GET"]
            action: allow
          - name: /a2a/stream
            httpVerb: ["POST"]
            action: deny
          - name: /a2a/*
            httpVerb: ["POST"]
            action: allow

This configuration applies the principle of least privilege:

  • Deny everything by default.
  • Allow the client app to fetch the agent card (/.well-known/agent-card.json).
  • Allow POST calls to /a2a/* for normal request/reply exchanges.

With this setup, the A2A server exposes only what’s required and nothing more,  Dapr enforces it automatically before any code runs. For more granular control, other application-level access control would be required.

4. Data Privacy and Confidentiality Requirements

A2A expects agents to protect sensitive data and comply with regulations like GDPR or HIPAA.
Key points:

  • Keep data encrypted in transit and at rest.
  • Share only what’s necessary (data minimization).
  • Follow enterprise or legal compliance policies.

How Dapr Solves This

Dapr adds strong security foundations for privacy-sensitive environments:

  • mTLS by default – All sidecar-to-sidecar traffic is encrypted and authenticated.
  • Secret stores – Dapr integrates with Kubernetes, Vault, AWS, Azure, and GCP secret managers to store credentials and tokens securely.
  • Secret API – Agents can retrieve secrets at runtime instead of embedding them in code:
  • Scoped access – Limit secret or component access to specific apps only.

GET http://localhost:3500/v1.0/secrets/secretstore/db-password

Dapr ensures encryption in transit and secure handling of credentials, while the agent remains responsible for applying data minimization and compliance policies.

5. Tracing, Observability, and Monitoring Requirements

A2A recommends operational visibility for every agent interaction:

  • Tracing of agent-to-agent calls
  • Logging for diagnostics
  • Metrics for monitoring
  • Auditing for compliance

These ensure that multi-agent systems can be debugged, tuned, and trusted in production.

How Dapr Solves This

Dapr has native observability with OpenTelemetry integration:

  • Tracing – Automatically captures spans for every Dapr-powered interaction.
  • Metrics – Exposes Prometheus-compatible metrics from every sidecar (/metrics endpoint).
  • Logs – Sidecar logs include request and system activity for auditing hooks.

Example configuration for the client agent:

apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
  name: appconfig
  namespace: default
spec:
  mtls:
    enabled: true
  metrics:
    enabled: true
  tracing:
    samplingRate: "1"
    zipkin:
      endpointAddress: "http://zipkin:9411/api/v2/spans"

This configuration enables mTLS for secure communication, exposes Prometheus-formatted metrics, and exports traces to Zipkin for visualization. With it, every A2A interaction becomes observable end-to-end, secure, measurable, and traceable without extra code.

6. Resilient Agent Interactions Requirements

A2A defines an inter-process protocol for agent-to-agent communication. In practice, agents can fail during upgrades, restarts, or network glitches. Without built-in resiliency, these transient failures result in lost requests or broken workflows. The A2A spec doesn’t define how to recover; it’s up to the implementation.

How Dapr Solves This

Dapr provides a Resiliency API for handling transient failures through retries, timeouts, and circuit breakers, all defined declaratively, no code changes needed.

Example resiliency policy for the client agent:

apiVersion: dapr.io/v1alpha1
kind: Resiliency
metadata:
 name: client-policy
scopes:
 - client
spec:
 policies:
   retries:
     slow-retry:
       policy: constant
       duration: 5s
       maxRetries: 5
       matching:
         httpStatusCodes: "500-599"
 targets:
   apps:
     server:
       retry: slow-retry

In this setup, any temporary errors (5xx responses) will be retried automatically. Combined with circuit breakers, timeouts, these policies make A2A interactions self-healing and resilient.

7. Agent Discovery Requirements

Before agents can collaborate, a client must first discover other agents and fetch their Agent Cards. The A2A specification outlines a few ways to find these cards: agents can expose them at a well-known URI (for example: ./.well-known/agent-card.json), they can be listed in curated registries maintained by organizations or marketplaces, or distributed via direct configuration in closed or private systems. There’s also an open proposal for a standard registry API, but there’s no established implementation yet, leaving discovery to the specific environment or deployment.

How Dapr Helps

While Dapr doesn’t replace A2A’s discovery mechanisms, it simplifies how agents locate and communicate with each other after discovery. When each agent runs with a Dapr sidecar, it automatically becomes addressable by its app ID, allowing other agents to connect by name instead of knowing hostnames or IPs.

Dapr supports multiple name resolution backends, including mDNS for local setups, Kubernetes DNS for clusters, Consul and AWS Cloud Map for enterprise environments, and even lightweight options like SQLite.

With this, a client agent can easily fetch another agent’s card through the Dapr sidecar:

GET http://localhost:3500/v1.0/invoke/server/method/.well-known/agent-card.json

Here, server is the app ID of the remote agent, resolved automatically by Dapr. In short, while A2A defines what to discover — the Agent Card — Dapr provides a consistent, cross-environment way to find and connect to agents once they are part of the same runtime network.

8. Concurrency and Rate Limiting Requirements

The A2A specification also highlights the need for resource management ensuring agents can protect themselves from overload or abuse:

Resource Management: Implement rate limiting, concurrency controls, and resource limits to protect agents from abuse or overload.” [source]

To prevent one misbehaving client or sudden traffic spike from taking an agent offline.

How Dapr Solves This

Dapr provides built-in tools for protecting agents under load, combining global concurrency control with fine-grained HTTP rate limiting:

  • Global Concurrency Control – The dapr.io/app-max-concurrency annotation limits the number of in-flight requests for each agent, covering service calls, pub/sub messages, and input bindings.
  • Rate Limiting Middleware – Dapr’s HTTP middleware can throttle requests per second per client IP, ensuring no single client can overwhelm the agent.
  • Request Size Limits – You can also restrict the maximum header and payload size to prevent memory exhaustion from oversized messages.

Example (annotations on a server agent deployment):

metadata:
  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "server"
    dapr.io/app-max-concurrency: "100"

These controls work alongside Dapr’s resiliency policies (retries, timeouts, circuit breakers) to create a strong defensive layer against overload, whether it’s a sudden burst of valid traffic, a buggy retry loop, or a denial-of-service scenario. For a deeper dive into rate limiting and overload protection, see the post Fault-Tolerant Microservices Made Easy with Dapr Resiliency.

9. External Access Requirements

A2A also recommends data and action-level authorization; agents should validate not only incoming requests, but also what they can access downstream, such as databases or external APIs. The agent acts as a gatekeeper to prevent unauthorized access to backend systems.

Dapr helps with this through component scoping, which limits which applications can use a particular resource (LLMs , state store, binding, secret store, etc.)  This ensures that even if multiple agents run in the same environment, each one can only access the components it is explicitly allowed to.

Example, giving access to a Redis state store only to the A2A server agent:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: redis-master:6379
scopes:
- server

Here:

  • Only the agent with the app ID server can access this statestore component.
  • Other agents or applications in the same namespace are automatically blocked.

This enforces clear separation of duties: authorization controls which clients may call an agent, and scoping controls which infrastructure resources that agent can touch.

How to add Dapr as a Drop-in Agent Companion

What if you could add all the missing layers: security, identity, access control, retries, metrics, and tracing, without rewriting your A2A agents? That’s exactly what we will show. Dapr runs as a sidecar next to your application, and by “Daprizing” your A2A client and server, you instantly gain enterprise-grade behavior without changing the agent logic. Here are the steps for the official A2A Java sample apps. To try out the full Daprized sample, follow the steps in this repository. At a high level, these are the steps:

Step 1 – Run a Sidecar Next to the Server Agent

Start the A2A server agent as usual, no code changes needed. Then, run a Dapr sidecar alongside it with access-control and mTLS enabled. This secures and governs all incoming traffic to the agent:

java -jar target/a2a-server-0.0.1-SNAPSHOT.jar

# on a separate terminal, run its sidecar

daprd \
--app-id server \
--app-port 8080 \
--app-protocol http \
--app-health-check-path "/.well-known/agent-card.json" \
--dapr-http-port 3501 \
--config resources/server-config.yaml \
--enable-mtls \
--sentry-address localhost:50001 \
--mode standalone

The configuration file (for example, server-config.yaml) defines mTLS, ACLs (see Dapr Access Control Lists) , metrics, and tracing as shown earlier. Now your server agent is protected by Dapr, all requests going through Dapr are authenticated, encrypted, and logged automatically.

Step 2 – Run a Sidecar Next to the Client Agent

Do the same for the client agent, but include resiliency and policy configurations so it can automatically retry transient failures or reconnect when the server restarts:

daprd \
--app-id client \
--dapr-http-port 3502 \
--dapr-grpc-port 4002 \
--config resources/client-config.yaml \
--resources-path resources \
--enable-mtls=true \
--sentry-address localhost:50001 \
--mode standalone

# on a separate terminal, start the client app

java -jar target/a2a-client-0.0.1-SNAPSHOT.jar

The configuration file (for example, client-config.yaml) defines mTLS but no ACLs. In addition, in the resources folder, we have the retry policy for the client to apply when interacting with the server agent.

Step 3 – Update the Client to Call Through Dapr

This is the only code change required. Instead of calling the server directly, the client calls the local Dapr sidecar, which forwards the request securely to the server sidecar.

Here’s the actual diff from the client Java example:

-        A2AClient client = new A2AClient("http://localhost:8080");
+        A2AClient client = new A2AClient("http://localhost:3502/v1.0/invoke/server/method/");

That’s it, a single line changed. Now the client talks to Dapr on port 3502, which handles service discovery, retries, encryption, and tracing behind the scenes.

Step 4 – Run and Test

Start both agents and observe the interaction. Kill or restart the server process: the client will automatically retry and recover, thanks to Dapr’s resiliency policy. Inspect the logs in Zipkin to see secure, observable A2A calls flowing through the sidecars. Without rewriting the agents, you’ve made A2A secure, reliable, and production-ready.

Here’s a concise summary with a call to action:

Summary

The A2A protocol defines interoperability for agents but leaves critical enterprise requirements—security, authentication, authorization, observability, resiliency, and discovery—up to the implementation. Dapr fills these gaps out of the box. By running Dapr sidecars next to A2A agents, you instantly gain enterprise-grade security and reliability without rewriting agent logic.

A2A Requirement Dapr Feature(s)
TLS mTLS + SPIFFE IDs (Sentry)
Authentication OAuth/OIDC middleware, App/Dapr API tokens, mTLS
Authorization ACL (service-to-service), component scoping, OAuth claims
Data Privacy & Confidentiality mTLS, Secret stores, data encryption, scoped access, scrub PII
Tracing & Observability OpenTelemetry, metrics, logs, auditing hooks
Resiliency Retries, timeouts, circuit breakers
Agent Discovery Service invocation + name resolution (mDNS, K8s DNS, Consul, AWS Cloud Map, SQLite, NameFormat)
Concurrency & Rate Limiting app-max-concurrency, rate limiting middleware
External Access Control Component scoping (limit resource use per app)

What’s On Our Roadmap

Dapr already makes A2A agents secure, reliable, and manageable, but a few capabilities are still needed to support A2A workloads fully.

First, streaming support is limited. A2A defines long-running interactions and event streams, while Dapr’s service invocation is mostly request/response. Native bidirectional or streaming RPC support would align it better with A2A’s communication model.

Second, more granular access control would help. Current ACLs work at the endpoint level, but being able to inspect the JSON-RPC message body would allow finer authorization, for example, enforcing rules per A2A method or skill.

Finally, smarter resiliency could improve reliability, such as retrying based on error codes in the JSON response rather than only HTTP status codes.

Adding these capabilities would make Dapr an even stronger runtime for agent-based systems, bringing operational guarantees and deeper awareness of the A2A protocol model.

Want to go deeper or try this in your environment?

No items found.