▲ 7 r/A2AProtocol+1 crossposts

Can AI agents change each other’s minds? I built a replayable A2A jury, and the verdict flipped

Most multi-agent demos show you the final answer while hiding the interesting part.

A coordinator calls several models, collects their responses, and writes a summary. But did the agents actually communicate? Who influenced whom? Did anyone revise their position, or were they simply multiple prompts running in parallel?

I built an open-source Agent-to-Agent, or A2A, experiment to make that interaction observable.

The setting is a fictional liability trial involving a robotaxi that struck and killed a cyclist. The evidence points to several interacting failures: an unvalidated software calibration, a moved road sign, an incorrect map, a network outage, and a braking policy that allowed camera classification to override radar.

The jury contains five autonomous agents with different professional perspectives:

  • A former collision detective
  • A civil-rights lawyer
  • A human-factors psychologist
  • A site-reliability engineer
  • An investigative journalist who acts as foreperson

These are not five prompts hidden behind one coordinator. Each participant is an explicit, addressable ProtoLink agent with its own identity, role, system prompt, model, task history, and A2A endpoint.

Every interaction crosses a real task boundary. One agent sends an addressed task directly to another agent and receives a structured result:

task = Task.create_infer(prompt=prompt)
result = await sender.call_agent(receiver.card.url, task)

The simulation engine controls the courtroom procedure and permitted communication topology. It does not write the agents’ arguments or choose whom a juror should contact.

In the mesh condition, each juror independently chooses:

  • Whom to address
  • Whether to ask, challenge, clarify, persuade, share evidence, or concede
  • What message to send
  • Which exhibits to cite
  • What public intent to declare

I compared two conditions using the same five jury roles, the same evidence, and the same public courtroom record.

Without juror-to-juror communication:

>2 guilty, 3 not guilty

With direct A2A communication:

>3 guilty, 2 not guilty

The majority-changing moment was visible in the event ledger.

The investigative journalist challenged the human-factors psychologist by connecting two exhibits: the vehicle was running an unvalidated calibration, and the reconstruction showed that calibration and road layout interacted to affect stopping safety.

Immediately after receiving that A2A message, the psychologist’s public position changed:

>77.90, not guilty, to 81.41, guilty

That categorical vote change created the new majority.

The probability and vote are recorded separately. A juror can consider guilt likely while still voting not guilty because the fictional criminal burden has not been satisfied. The application never turns a probability above 50 percent into an automatic guilty vote.

The generated report lets you replay the entire process:

  • Sender and receiver for every A2A task
  • The agent-authored question or challenge
  • Evidence citations
  • The receiver’s public reply
  • Before-and-after decision registers
  • Categorical vote changes
  • Routing and validation failures
  • Retries, latency, and protocol traces
  • The final influence graph

It does this without exposing private chain-of-thought. The replay contains public agent outputs, application state changes, and observable A2A protocol events.

An important limitation: the offline reference run is deterministic and deliberately designed to make the communication treatment visible. It does not prove that direct communication generally makes agents smarter. An opinion change immediately after a message also does not prove that the message caused the entire change.

The honest conclusion is narrower:

Direct A2A communication changed the collective outcome, and the architecture made the path to that change inspectable.

The next step is to repeat the experiment across models and seeds, then remove or replace individual messages to see whether the vote change survives.

ProtoLink is an A2A-first Python framework. The example can run completely offline, use local models through Ollama, or connect different agents to OpenAI, Anthropic, Gemini, and OpenAI-compatible backends.

A really interesting test that could extend the current example:

Because every agent can use a different model, this can also become a controlled LLM benchmark. Keep the case, evidence, jury, prompts, and communication topology fixed, then assign different LLMs to represent the defendant and the opposing side. By rotating models such as GPT, Claude, Gemini, Qwen, or local models through each role, we can measure how each one affects juror opinions, vote changes, and the final outcome.

It is free, open source, and MIT-licensed. I am the author of ProtoLink and the linked article.

Source code:
https://github.com/nMaroulis/protolink/tree/main/examples/ai_courtroom

Full technical write-up:
https://levelup.gitconnected.com/can-ai-agents-change-each-others-minds-9162ed3a3ae1

For multi-agent systems, should the goal be consensus, or should it be making disagreement and influence traceable ?

reddit.com
u/sheik66 — 11 days ago
▲ 2 r/A2AProtocol+1 crossposts

Building an A2A-Native Agent Runtime: How I extended the spec with runtime context and structured flows

Hi everyone,

I wanted to share a project I've been working on called Protolink (https://github.com/nMaroulis/protolink). I’d love to get some honest feedback from this community on the approach I took.

The Honest Start: Why I Built This

I’m not going to start with the typical "I got tired of LangChain/LangGraph so I built something better" pitch. The truth is, I read through Google's Agent-to-Agent (A2A) protocol specification and loved the philosophy, to treat agent communication as structured, typed, and decoupled distributed messages.

However, when I actually sat down to build a multi-agent system using raw A2A guidelines, I realized how much infrastructure boilerplate I had to write:

  • Setting up separate client and server applications for every single agent.
  • Manually handling discovery and registry lookups.
  • Wiring up LLM inference loops, parsing raw JSON, and writing tool-calling logic (especially fallback modes for smaller, local models that don't support native tool calling).
  • Orchestrating tasks without a clean runtime state-machine model.

So, I started building Protolink. I wanted to see if I could create adeveloper-first, A2A-native agent runtime that abstracts away all the network and LLM boilerplate while remaining fully compliant with the protocol.

How Protolink Extends A2A with Runtime Context

In Google's A2A spec, details like LLM invocation, tool execution, and local-versus-remote transport are largely out of scope. Protolink extends the spec by unifying them into a single, cohesive runtime concept: the Agent.

  1. Unified Agent Model: Instead of maintaining separate client and server codebases, a Protolink Agent contains both a client and a server. It owns its lifecycle, storage, and transport layer.
  2. First-Class LLM & Tool Loops: Protolink manages the LLM inference loop. It takes care of mapping schemas to different model APIs (OpenAI, Anthropic, Gemini, Ollama) and handles JSON fallbacks for smaller models.
  3. In-Process transport (runtime): This is probably the biggest quality-of-life feature. Running multiple agents across separate HTTP/WebSocket servers during local development is a headache. Protolink implements an in-process, shared-memory transport. You can run and test an entire agent mesh in a single Python process. When you're ready to deploy, you change transport="runtime" to transport="http" or transport="websocket" in the config, where no agent logic changes required.

The Runtime Layer: Managing the execution Lifecycle

While A2A defines what travels through the system (the payload: TaskMessageArtifactPart), a real-world application needs to control how it executes. Protolink introduces a structured runtime layer that wraps execution with stable security, monitoring, and control boundaries:

  • RunContext (Typed Execution Envelope): Ad hoc metadata keys like session_idtrace_id, and workspace_uri are replaced with a single serializable object. When tasks are delegated downstream, RunContext.child() automatically propagates workspace paths, trace IDs, permission boundaries, and run budgets (max_stepsmax_llm_calls) while establishing parent-child relationships.
  • Cooperative Cancellation: Interrupting long-running asynchronous tasks (especially multi-agent loops or streams) is notoriously tricky. Protolink handles cancellation at the runtime level. Calling client.cancel_task() propagates a cancellation state through HTTP/WebSocket/Runtime transports, and the local agent triggers a process-safe CancellationToken checkpoint. It stops CPU loops, async tool calls, or model streams gracefully at the next await boundary without losing task execution history.
  • Capability Policies & Human-in-the-Loop Approvals: We normalize all LLM decisions into a provider-independent RunAction before any side effects happen. If an action requires a protected capability (e.g., records.write), the CapabilityPolicy evaluates it. If it requires approval, the agent pauses, creates an ApprovalRequest with preview artifacts (so users see exactly what will write to disk or database), and triggers an application-level handler (like a CLI prompt or a web UI modal) before executing.
  • Normalized Event Streams (RunEvent): Transports can emit messy, custom events. Protolink wraps these into a single versioned RunEvent stream (e.g., action.requestedapproval.requiredtask.statusllm.stream) sent to an EventSink. This means terminal UIs, log aggregators, or telemetry monitors can switch on a unified schema regardless of the underlying LLM provider.

Structured Flows Using A2A Primitives

Most agent frameworks use external graph engines (like LangGraph or custom DAG builders) to coordinate agent interactions. In Protolink, I wanted the workflow orchestration to remain protocol-native.

A Protolink Structured Flow is a deterministic state machine that operates directly over A2A primitives: TaskMessageArtifact, and Part. The flow orchestrator expects a Task and returns a Task.

We support several topologies out of the box:

  • Pipeline: A sequential chain of agents.
  • Parallel: Broadcasting tasks to concurrent agents with safe ID-based fan-in merging to prevent duplicate artifacts.
  • Router: Conditional branching based on structured, serializable Part.route(...) decisions.
  • Graph: Full state-machines that support loops and cycle back on validation failures.

🧠 The Secret Sauce: Semantic Context Injection

How do you run structured flows without tightly coupling the agents to the flow topology?

We use Dynamic Semantic Context Injection:

  1. Before sending a task to an agent, the Flow orchestrator looks at the downstream step in the topology.
  2. It fetches the downstream agent's description and capabilities (AgentCard) from the Registry.
  3. It dynamically builds a system prompt (e.g., "Your output will go to the 'Summarizer' agent, which expects X formatting" or "You are broadcasting to a committee of ['Editor', 'Security_Inspector']") and attaches it to the Task's flow_state.
  4. The executing agent automatically merges this prompt into its system prompt during LLM inference, adapting its output layout at runtime to suit the downstream consumer.

Cool Usages: What Can You Build?

Here are two cool examples of what this looks like in practice:

1. A Local "Claude Code" Clone (~3 Agents)

I built a mini "Claude Code" coding assistant by composing three specialized agents:

  • Orchestrator Agent (Coordinator): Receives the user request, lists files, and coordinates.
  • Planner Agent (Brain): Pure LLM-only agent. Has no filesystem access. It receives the code and generates high-level plans or precise refactoring edits.
  • Coder Agent (hands): Tools-only agent (no LLM). It executes deterministic operations like reading/writing files and searching directories.

The Orchestrator coordinates them using standard A2A delegation modes: calling the Coder with tool_call parts, and calling the Planner with infer parts. The code stays clean because the concerns are completely separated.

2. Deep Composition (Pipeline -> Parallel -> Pipeline)

Because all flows are polymorphic and recursively nestable, you can nest parallel committees inside a pipeline:

pythonfrom protolink.flows import Pipeline, Parallel
from protolink.agents import Agent
from protolink.models import Task
# 1. Spin up some agents
researcher = Agent(card={"name": "researcher", "url": "http://localhost:8081"}, ...)
sec_inspector = Agent(card={"name": "security_inspector", "url": "http://localhost:8082"}, ...)
fmt_inspector = Agent(card={"name": "format_inspector", "url": "http://localhost:8083"}, ...)
summarizer = Agent(card={"name": "summarizer", "url": "http://localhost:8084"}, ...)
# 2. Build a Parallel Flow representing a review committee
review_committee = Parallel(
    branches=["security_inspector", "format_inspector"], 
    registry=registry
)
# 3. Nest the Parallel block as a step inside a Parent Pipeline
orchestrated_flow = Pipeline(registry=registry) \
    .add_step(researcher) \
    .add_step(review_committee) \
    .add_step(summarizer)
# 4. Execute standard A2A task
task = Task.create_infer(prompt="Audit and summarize the codebase's WebSocket implementation.")
result = await orchestrated_flow.execute(task)

I'd Love Your Feedback !

I wanted to build an agent framework that acts like a predictable, observable distributed system rather than a black box.

I'd love to hear your thoughts:

  • Does this align with how you see A2A scale in production?
  • How would you balance structured state-machine flow control with agent autonomy in your projects?
  • What are your thoughts on Semantic Context Injection vs. hardcoded agent interactions?
  • How would you manage human-in-the-loop safety approvals and cooperative cancellation in your own architectures?

Check it out here: https://github.com/nMaroulis/protolink And the docs: https://nmaroulis.github.io/protolink/ and a medium post on Level-Up-Code: https://levelup.gitconnected.com/build-easily-your-own-claude-code-with-three-agents-brain-hands-and-coordinator-5236b392ddf0

Let me know what you think!

u/sheik66 — 2 months ago

Struggling to get local models working well in Zed. Thinking of building a dedicated local ACP server.

I absolutely love Zed’s speed, but I’ve been hitting a wall trying to get a reliable, local-first agent workflow going to save on API costs. [Mac mini user 16GB RAM :( ]

I’ve tried plugging smaller local models (like Qwen 2.5, Gemma e4b etc) directly into Zed’s built-in agent panel, but they clearly aren't smart enough to handle Zed's default system prompts and they just hallucinate or break the formating. I also gave cline a shot, but honestly found it pretty unreliable and flaky for everyday use.

I really just want a more robust agent orchestration loop, but engineered explicitly to hand-hold local models through the code generation process, right inside Zed.

Since I couldn't find anything lightweight and I also find it a really interesting topic (especially the agent orchestration), I started hacking together a proof of concept using the Agent Client Protocol (ACP).

The idea is:

  • A purely local orchestration engine (Python): Handles the multi-agent loop (Planner -> Coder -> Critic) specifically tuned for the quirks of local Ollama/LM Studio models.
  • ProtoAgent ACP Server: It brings that orchestration natively into Zed. Zed handles the beautiful UI, while the ACP server intercepts the requests, does the complex agent routing in the background, and feeds the clean, final diffs back to Zed so the model doesn't get confused.

Before I spend my free time fully building out the server and open-sourcing it, I wanted to ask:

  1. Has anyone actually gotten local 7B/8B models working reliably with Zed's native agent without them losing their minds?
  2. Is there an existing ACP/MCP server doing this specifically for local models that I completely missed?
  3. Would you actually use a dedicated local-first orchestration server designed to plug into Zed?

Would love to hear how you guys are handling local AI code generation right now.

reddit.com
u/sheik66 — 2 months ago