Advanced Topics
Agent Consensus
Voting-based response aggregation for multi-agent systems
Agent Consensus
Agent Consensus provides voting-based response aggregation for multi-agent AI systems.
Overview
When multiple AI agents process the same query, their responses may differ. Agent Consensus:
- Collects responses from multiple agents
- Counts votes for each unique response
- Returns the response that meets the threshold
- Optionally requires cryptographic signatures
Configuration
struct AgentConsensusConfig {
threshold @0 :Float64; # Required vote fraction (0.0-1.0)
minResponses @1 :UInt32; # Minimum responses before consensus check
timeoutSecs @2 :UInt32; # Query timeout in seconds
requireSignatures @3 :Bool; # Whether agent signatures are required
}Example configurations:
| Use Case | Threshold | Min Responses |
|---|---|---|
| Simple majority | 0.5 | 3 |
| Supermajority | 0.67 | 5 |
| Unanimous | 1.0 | 3 |
| First response | 0.0 | 1 |
Query Lifecycle
Submit Query
struct AgentSubmitQueryRequest {
query @0 :Text;
config @1 :AgentConsensusConfig;
}
struct AgentSubmitQueryResponse {
queryId @0 :AgentQueryId;
}Collect Responses
Agents submit their responses:
struct AgentSubmitResponseRequest {
queryId @0 :AgentQueryId;
agentId @1 :Text;
response @2 :Text;
signature @3 :Data; # Optional signature
confidence @4 :Float32; # Agent's confidence (0.0-1.0)
}Check Consensus
struct AgentTryConsensusResponse {
union {
result @0 :Text; # Consensus reached
pending @1 :AgentQueryState; # Still collecting
noConsensus @2 :AgentQueryState; # Min met, no consensus
error @3 :Text;
}
}Query State
struct AgentQueryState {
queryId @0 :AgentQueryId;
query @1 :Text; # Original query
responses @2 :List(AgentResponseEntry);
votes @3 :List(AgentResponseVote);
finalized @4 :Bool;
result @5 :Text; # Final result (if finalized)
createdAt @6 :Timestamp;
}
struct AgentResponseVote {
responseHash @0 :Data; # BLAKE3 hash of response
voteCount @1 :UInt32;
voters @2 :List(Text); # Agent IDs that voted
}Consensus Service
interface AgentConsensusService {
# Submit a new query for consensus
submitQuery @0 (request :AgentSubmitQueryRequest) -> (response :AgentSubmitQueryResponse);
# Submit an agent's response to a query
submitResponse @1 (request :AgentSubmitResponseRequest) -> (result :AgentSubmitResponseResult);
# Try to reach consensus on a query
tryConsensus @2 (request :AgentTryConsensusRequest) -> (response :AgentTryConsensusResponse);
# Get current query state
getQuery @3 (queryId :AgentQueryId) -> (state :AgentQueryState);
# Clean up expired queries
cleanup @4 () -> ();
# Get number of active queries
activeQueries @5 () -> (count :UInt32);
}Usage Examples
Rust
use zap_protocol::consensus::{AgentConsensus, ConsensusConfig};
// Create consensus service
let consensus = AgentConsensus::new();
// Submit query
let query_id = consensus.submit_query(
"What is the capital of France?",
ConsensusConfig {
threshold: 0.67,
min_responses: 3,
timeout_secs: 30,
require_signatures: false,
}
).await?;
// Agents submit responses (from different agents)
consensus.submit_response(&query_id, "agent-1", "Paris", None, 0.95).await?;
consensus.submit_response(&query_id, "agent-2", "Paris", None, 0.90).await?;
consensus.submit_response(&query_id, "agent-3", "Lyon", None, 0.60).await?;
// Check consensus
match consensus.try_consensus(&query_id).await? {
ConsensusResult::Result(answer) => {
println!("Consensus: {}", answer); // "Paris"
}
ConsensusResult::Pending(state) => {
println!("Still collecting: {}/{}",
state.responses.len(),
config.min_responses);
}
ConsensusResult::NoConsensus(state) => {
println!("No consensus reached");
for vote in &state.votes {
println!(" {} votes: {}", vote.vote_count, vote.voters.len());
}
}
}Go
import "github.com/zap-protocol/zap-go/consensus"
// Create service
svc := consensus.NewAgentConsensus()
// Submit query
queryID, _ := svc.SubmitQuery(ctx, "What is 2+2?", &consensus.Config{
Threshold: 0.67,
MinResponses: 3,
TimeoutSecs: 30,
})
// Submit responses
svc.SubmitResponse(ctx, queryID, "agent-1", "4", nil, 0.99)
svc.SubmitResponse(ctx, queryID, "agent-2", "4", nil, 0.99)
svc.SubmitResponse(ctx, queryID, "agent-3", "4", nil, 0.99)
// Check consensus
result, _ := svc.TryConsensus(ctx, queryID)
fmt.Println("Answer:", result) // "4"Python
from zap_protocol.consensus import AgentConsensus, ConsensusConfig
# Create service
consensus = AgentConsensus()
# Submit query
query_id = await consensus.submit_query(
"Translate 'hello' to French",
ConsensusConfig(
threshold=0.5,
min_responses=3,
timeout_secs=30
)
)
# Submit responses
await consensus.submit_response(query_id, "agent-1", "bonjour")
await consensus.submit_response(query_id, "agent-2", "bonjour")
await consensus.submit_response(query_id, "agent-3", "salut")
# Check consensus
result = await consensus.try_consensus(query_id)
print(f"Translation: {result}") # "bonjour"Signature Verification
When requireSignatures is true:
// Agent signs response with ML-DSA
let signature = identity.sign(response.as_bytes())?;
consensus.submit_response(
&query_id,
"agent-1",
response,
Some(signature),
0.95
).await?;The consensus service verifies signatures against registered agent identities.
Response Hashing
Responses are compared by BLAKE3 hash:
let hash = blake3::hash(response.as_bytes());This ensures:
- Identical responses are grouped together
- Whitespace/formatting differences are not tolerated
- Large responses are efficiently compared
Confidence Weighting
Optionally, votes can be weighted by confidence:
let config = ConsensusConfig {
threshold: 0.67,
min_responses: 3,
timeout_secs: 30,
require_signatures: false,
weight_by_confidence: true, // Enable weighting
};With weighting:
- High-confidence responses count more
- Threshold applies to weighted sum
- Low-confidence responses may be filtered
Cleanup
Expired queries should be cleaned up periodically:
// Clean up queries older than timeout
consensus.cleanup().await?;
// Get active query count
let count = consensus.active_queries().await?;Best Practices
- Set Appropriate Thresholds: Higher for critical decisions
- Minimum Responses: At least 3 for meaningful consensus
- Timeouts: Balance between wait time and response collection
- Signatures: Enable for production deployments
- Monitoring: Track consensus success rates
Last updated on