Skip to main content

v0.21.0 Release Notes

EnerOS v0.21.0 Release Notes

Release Date: June 22, 2025 Codename: Swarm Git Tag: v0.21.0 Support Status: Stable Total Crates: 48 (6 new) Test Cases: 6100+ (700+ new)

Overview

EnerOS v0.21.0 “Swarm” is the first version of EnerOS’s “Multi-Agent Collaboration” phase, focusing on Multi-Agent Collaboration. Prior to this version, EnerOS’s Agent runtime could support single Agents completing tasks such as dispatch, inspection, and trading, but real-world power system business scenarios often require dozens or even hundreds of Agents working collaboratively—for example, a provincial dispatch center might simultaneously run 200+ Agents covering generation dispatch, load forecasting, renewable energy integration, fault localization, and inspection scheduling. v0.21.0 brings “Multi-Agent Collaboration” from the application layer down to a kernel first-class capability.

This version introduces a complete multi-agent collaboration framework: Agent Communication Protocol (ACP), Task Dispatcher, Negotiation Protocol, and Collective Decision engine. Agents are no longer isolated processes but form an orchestrable, observable, and governable “Swarm.” The swarm can automatically form collaborative relationships based on grid topology—for example, when a line fault occurs, the fault localization Agent, isolation Agent, load transfer Agent, and inspection Agent automatically form a temporary collaboration group based on electrical connectivity, automatically disbanding after fault handling is complete.

The core design philosophy of v0.21.0 is “grid topology determines collaboration topology”—Agent collaboration relationships are not hard-coded by developers but dynamically derived from the grid’s electrical connectivity, equipment jurisdiction, and safety responsibility boundaries. This gives collaboration electrical semantics: when topology changes (switch operations, equipment commissioning/decommissioning), Agent collaboration relationships automatically rebalance.

Key Metrics

MetricValueDescription
Collaborative Agent scale1-1024Single cluster support
Agent communication latency P99180μsSame-node shared memory
Task dispatch latency P99850μsSame node
Negotiation latency< 50ms3-node PBFT
Collective decision throughput120K/sSingle cluster
New Crates6Collaboration-related
New tests700+Including 80 end-to-end

New Features

1. Multi-Agent Collaboration Framework

Introduced the eneros-swarm Crate, providing a complete multi-agent collaboration runtime. A Swarm is a logical collection of collaborating Agents with independent lifecycle, shared context, unified task queue, and observable collaboration graph.

Swarm Data Structure

use eneros_swarm::{Swarm, SwarmConfig, SwarmId, AgentRole, Permission};
use eneros_swarm::consensus::ConsensusProtocol;

// Create a swarm
let mut swarm = Swarm::new(SwarmId::from("dispatch-swarm-1"))
    .config(SwarmConfig {
        max_agents: 64,
        task_queue_capacity: 4096,
        consensus_protocol: ConsensusProtocol::Pbft,
        topology_aware: true,
        auto_rebalance: true,
    });

// Register Agent roles
swarm.register_role(AgentRole::new("coordinator")
    .replicas(1)
    .permission(Permission::DispatchCommand))?;

swarm.register_role(AgentRole::new("executor")
    .replicas(8)
    .permission(Permission::ExecuteCommand))?;

swarm.register_role(AgentRole::new("observer")
    .replicas(4)
    .permission(Permission::ReadOnly))?;

// Start the swarm
swarm.start().await?;

Automatic Collaboration Topology Building

Swarm automatically builds communication topology between Agents based on grid topology, giving collaboration relationships electrical semantics:

// Automatically build collaboration relationships based on electrical connectivity
swarm.bind_to_topology(&network)?;

// When topology changes (switch operation), collaboration relationships automatically rebalance
network.on_event(TopologyEvent::SwitchOpened(switch_id), |event| {
    swarm.rebalance_on_topology_change(event);
});

Comparison with Traditional Approaches

DimensionTraditional (Application-layer orchestration)EnerOS Swarm (Kernel first-class citizen)
Collaboration relationship sourceDeveloper hard-codedTopology-derived
Topology change responseService restartAutomatic rebalancing
Communication mechanismExternal middlewareKernel shared memory
FailoverManual configurationAutomatic election
ObservabilityApplication logsCollaboration graph + tracing

2. Agent Communication Protocol (ACP)

Introduced eneros-swarm-acp (Agent Communication Protocol), defining a unified protocol for message exchange between Agents. ACP draws on FIPA-ACL semantics and extends electrical semantic primitives for power scenarios.

Message Types

Message TypeSemanticsPower Scenario Example
RequestRequest executionRequest switch operation
InformNotify factNotify fault location result
QueryQuery informationQuery bus voltage
ProposeMake proposalPropose load transfer plan
AcceptAccept proposalAccept transfer plan
RejectReject proposalReject out-of-limit plan
SubscribeSubscribe to eventSubscribe to topology changes
CoordinateCoordinate actionsCoordinate multi-Agent isolation

Message Structure

use eneros_swarm_acp::{AcpMessage, Performative, AgentId};

let msg = AcpMessage::new()
    .from(AgentId::from("fault-locator-1"))
    .to(AgentId::from("isolator-3"))
    .performative(Performative::Inform)
    .content(FaultLocation {
        bus_id: 42,
        distance_km: 3.2,
        confidence: 0.97,
    })
    .ontology("grid-fault")
    .reply_by(Duration::seconds(5));

swarm.send(msg).await?;

Transport Layer

ACP supports multiple transport backends, automatically selecting the optimal path based on Agent location:

use eneros_swarm_acp::transport::{Transport, SharedMemory, TcpTransport};

// Same node: shared memory + lock-free queue (180μs)
let local = Transport::SharedMemory(SharedMemory::new()
    .ring_size(4096)
    .zero_copy(true));

// Cross-node: TCP + Protobuf (2.3ms)
let remote = Transport::Tcp(TcpTransport::new()
    .compression(Compression::Zstd)
    .tls(TlsConfig::from_file("agent.crt")?));

swarm.set_transport(local, remote);

Transport Performance Comparison

TransportLatency P99ThroughputUse Case
Shared memory180μs500K/sSame node
Unix socket350μs200K/sSame host cross-process
TCP local800μs100K/sSame rack
TCP cross-node2.3ms50K/sCross-host

3. Task Decomposition and Dispatch

Introduced eneros-swarm-dispatcher, providing Task Decomposition and Dispatch capabilities. Complex tasks are automatically decomposed into subtasks, selecting appropriate Agents based on electrical semantics, priority, and load.

Task Decomposition

use eneros_swarm_dispatcher::{Dispatcher, Task, Decomposer};

let dispatcher = Dispatcher::new(&swarm);

// Complex task auto-decomposition
let complex_task = Task::new("fault-handling")
    .payload(FaultEvent {
        bus_id: 42,
        fault_type: FaultType::ShortCircuit,
    });

let subtasks = Decomposer::decompose(&complex_task)?;
// Decomposed into:
// 1. fault-location
// 2. fault-isolation
// 3. load-transfer
// 4. inspection

for sub in subtasks {
    dispatcher.dispatch(sub).await?;
}

Dispatch Strategies

use eneros_swarm_dispatcher::DispatchStrategy;

// Strategy 1: Nearest dispatch (closest electrical distance)
dispatcher.strategy(DispatchStrategy::NearestByElectricalDistance);

// Strategy 2: Load balancing
dispatcher.strategy(DispatchStrategy::LeastLoaded);

// Strategy 3: Affinity dispatch (same region preferred)
dispatcher.strategy(DispatchStrategy::Affinity {
    key: "region_id",
    sticky: true,
});

// Strategy 4: Priority dispatch
dispatcher.strategy(DispatchStrategy::Priority {
    high_priority_agents: vec!["executor-0", "executor-1"],
});

// Dispatch task
let task = Task::new("check-bus-1")
    .target(BusId::from(1))
    .priority(Priority::High)
    .deadline(Duration::seconds(30));

let handle = dispatcher.dispatch(task).await?;
let result = handle.await?;

Dispatch Strategy Performance

Dispatch StrategyScheduling Latency P99ThroughputUse Case
Nearest850μs50K/sFault handling
Load balancing1.2ms120K/sBatch tasks
Affinity950μs80K/sRegional tasks
Priority1.5ms60K/sUrgent tasks

4. Negotiation Mechanism

Introduced eneros-swarm-negotiation, providing multiple negotiation protocols to ensure multi-Agent consensus on critical decisions. Power system critical operations (switch operations, generator output adjustments, load shedding) must undergo negotiation to prevent single-point errors from causing grid incidents.

Negotiation Protocol Selection

use eneros_swarm_negotiation::{Negotiator, Protocol};

// PBFT: 3-7 node small cluster, strong consistency
let negotiator = Negotiator::new(Protocol::Pbft {
    n: 3,
    f: 0,
    timeout: Duration::milliseconds(500),
});

// Raft: 3-9 nodes, CP system
let negotiator = Negotiator::new(Protocol::Raft {
    election_timeout: Duration::milliseconds(150),
    heartbeat_interval: Duration::milliseconds(50),
});

// Gossip: Large-scale eventual consistency
let negotiator = Negotiator::new(Protocol::Gossip {
    fanout: 6,
    interval: Duration::milliseconds(100),
});

Critical Operation Negotiation

// Switch operations must undergo negotiation
let proposal = NegotiationProposal::new("open-switch-42")
    .payload(Command::OpenSwitch { id: 42 })
    .required_quorum(Quorum::TwoThirds)
    .timeout(Duration::seconds(5));

match negotiator.propose(proposal).await {
    Ok(consensus) => {
        ctx.syscall(ExecuteCommand(consensus.command)).await?;
    }
    Err(NegotiationError::Timeout) => {
        log::warn!("Switch operation failed to reach negotiation consensus");
    }
}

Negotiation Protocol Comparison

ProtocolNode CountConsistencyLatencyFault ToleranceUse Case
PBFT3-7Strong< 50msf < n/3 ByzantineCritical operations
Raft3-9Strong< 100msf < n/2 crashConfiguration changes
GossipAnyEventual100ms-1sAny partitionState synchronization

5. Collective Decision

Introduced eneros-swarm-collective, supporting multi-Agent collective decision-making. When multiple Agents propose different solutions (such as multiple load transfer plans), the optimal solution is selected through voting, weighting, auction, and other mechanisms.

Decision Modes

use eneros_swarm_collective::{CollectiveDecision, Voting, Auction};

// Mode 1: Majority voting
let decision = CollectiveDecision::new(Voting::Majority)
    .proposals(vec![plan_a, plan_b, plan_c])
    .voters(all_agents)
    .decide().await?;

// Mode 2: Weighted voting (by Agent weight)
let decision = CollectiveDecision::new(Voting::Weighted)
    .proposals(vec![plan_a, plan_b])
    .weight("dispatcher", 5.0)
    .weight("protection", 3.0)
    .decide().await?;

// Mode 3: Auction (highest bidder wins)
let auction = Auction::new("load-transfer-job")
    .bidders(executors)
    .bid_fn(|agent| agent.estimate_cost(&job))
    .settle().await?;

Decision Recording

All collective decisions are persisted for audit, including proposals, votes, results, and timestamps:

// Decision records are traceable
let record = decision.record();
assert!(record.proposals.len() == 3);
assert!(record.winner == "plan_b");
assert!(record.votes_for == 5);
assert!(record.votes_against == 2);

Improvements

  • Agent Communication: Changed inter-Agent communication from TCP-based to shared memory + lock-free queue, reducing single-node message latency from 2.3ms to 180μs
  • Topology-aware Scheduling: Scheduler now senses electrical island boundaries, avoiding cross-island task dispatch
  • Observability: New eneros-swarm-trace Crate, providing collaboration graph visualization
  • Failure Detection: Agent heartbeat detection reduced from 5 seconds to 500ms, more timely fault discovery
  • Resource Isolation: Each Swarm has independent task queue and memory pool, avoiding mutual interference

Bug Fixes

  • Fixed eneros-agent scheduler deadlock when Agent count exceeds 64 (#2103)
  • Fixed eneros-agent memory leak where Agent context was not cleaned up after heartbeat timeout (#2107)
  • Fixed eneros-topology high broadcast latency for topology change events in Swarm mode (#2112)
  • Fixed eneros-constraint race condition during concurrent multi-Agent validation (#2118)
  • Fixed eneros-timeseries timezone handling error in aggregation queries (#2120)

Breaking Changes

  • Agent::run signature change: New swarm_ctx: &SwarmContext parameter; original signature migrated to Agent::run_standalone
  • Dispatcher::dispatch return type: Changed from Result<TaskResult> to Result<TaskHandle>, requires .await to get result
  • ConsensusEngine rename: Unified to Negotiator, original name retained as alias until v0.25.0

Upgrade Guide

Upgrading from v0.20.0 to v0.21.0:

  1. Run cargo update -p eneros-swarm
  2. Replace Agent::run calls with Agent::run_standalone, or migrate to Swarm mode
  3. Update Dispatcher::dispatch calls to adapt to new TaskHandle return type
  4. Refer to docs/migration/v0.21.0.md for detailed migration steps

Acknowledgments

Thanks to the 12 contributors who participated in this version’s development, with special thanks to the scheduling algorithm, consensus protocol, and communication transport working groups for their hard work.