| Crates.io | converge-core |
| lib.rs | converge-core |
| version | 1.0.0 |
| created_at | 2026-01-07 14:23:17.498252+00 |
| updated_at | 2026-01-24 18:42:00.863633+00 |
| description | Converge Agent OS - correctness-first, context-driven multi-agent runtime |
| homepage | |
| repository | |
| max_upload_size | |
| id | 2028321 |
| size | 1,350,079 |
Context is the only shared state. The engine decides; agents propose.
A correctness-first, context-driven multi-agent runtime library.
Website: converge.zone | Docs: docs.rs | Crates.io: converge-core
Converge Core is the foundational semantic engine of the Converge ecosystem. It provides:
| Aspect | Description |
|---|---|
| The authority | The engine decides what becomes a Fact |
| Context owner | Context is the API; all collaboration happens through it |
| Convergence guarantor | Execution proceeds until a fixed point is reached |
| Invariant enforcer | Constraints are checked continuously and at convergence |
| Trait definer | Defines Agent, LlmProvider, Embedding, etc. |
| Anti-pattern | Why Not |
|---|---|
| Not a workflow engine | No predefined steps; agents react to context |
| Not an event bus | No pub/sub; context changes trigger eligibility |
| Not an actor system | Agents never call each other; no message passing |
| Not eventual consistency | Convergence is explicit and observable |
| Not provider implementations | Providers live in converge-provider |
These are the non-negotiable principles that define Converge.
Agents do not call each other. They read Context and emit effects. Context is the API.
Agents return AgentEffect containing Fact or ProposedFact.
The engine validates, merges, and commits.
Execution proceeds until:
Context_{n+1} == Context_n (fixed point), orWrong answers are worse than no answers. Invariants block invalid states.
Same input → same output. All decisions are traceable.
LLM outputs become ProposedFact, not Fact.
Validators promote proposals after verification.
Beyond the core axioms, Converge is built on a systems-level understanding of converging flows.
A converging flow is a goal-directed, multi-agent process where:
All flows decompose into six structural phases:
Intent → Framing → Exploration → Tension → Convergence → Commitment
If any phase is missing, the system oscillates, over-optimizes locally, or produces brittle outcomes.
Intent must be explicit. Without declared intent, convergence must not begin.
Constraints precede exploration. Exploration without surfaced constraints produces invalid outcomes.
Tension is mandatory. If multiple perspectives immediately agree without conflict, force contradiction search.
Commitment freezes state. The system must commit or explicitly defer — no ambiguous endings.
Flows are classified by dominant uncertainty:
See converge-business/knowledgebase/core-CONVERGING_FLOWS.md for the complete flow theory.
┌─────────────────────────────────────────────────────────────────┐
│ converge-core │
│ The foundational layer. Depends on NOTHING in the ecosystem. │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Engine │ │ Context │ │ Invariant │ │
│ │ (decides) │───▶│ (shared) │◀───│ (guards) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ ▲ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Agent │───▶│ AgentEffect │ │
│ │ (proposes) │ │ (buffered) │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ Trait Definitions: │
│ • Agent • LlmProvider • Embedding │
│ • Invariant • VectorRecall • GraphRecall │
│ • Reranking • ModelSelector │
│ │
└─────────────────────────────────────────────────────────────────┘
│
│ implements traits
▼
┌─────────────────────────────────────────────────────────────────┐
│ converge-provider │
│ Capability adapters (Anthropic, OpenAI, Gemini, etc.) │
└─────────────────────────────────────────────────────────────────┘
│
│ uses providers in agents
▼
┌─────────────────────────────────────────────────────────────────┐
│ converge-domain │
│ Domain agents, use cases, business logic │
└─────────────────────────────────────────────────────────────────┘
| Crate | May Depend On | Must NOT Depend On |
|---|---|---|
converge-core |
(nothing) | converge-provider, converge-domain |
converge-provider |
converge-core |
converge-domain |
converge-domain |
converge-core, converge-provider |
— |
[dependencies]
converge-core = "0.6"
| Crate | Version | Description |
|---|---|---|
| converge-core | 0.6.2 | Runtime engine, agent traits, capabilities |
| converge-provider | 0.2.4 | 14+ LLM providers, model selection |
| converge-domain | 0.2.4 | 12 business use cases |
use converge_core::{Engine, Context, ContextKey, Fact, Agent, AgentEffect};
// Define a simple agent
struct GreetingAgent;
impl Agent for GreetingAgent {
fn name(&self) -> &str { "greeting" }
fn dependencies(&self) -> &[ContextKey] { &[ContextKey::Seeds, ContextKey::Signals] }
fn accepts(&self, ctx: &Context) -> bool {
ctx.has(ContextKey::Seeds) &&
!ctx.get(ContextKey::Signals).iter().any(|f| f.id.starts_with("greeting-"))
}
fn execute(&self, _ctx: &Context) -> AgentEffect {
AgentEffect::with_fact(Fact::new(
ContextKey::Signals,
"greeting-response",
"Hello from Converge!",
))
}
}
fn main() {
let mut engine = Engine::new();
engine.register(GreetingAgent);
let mut ctx = Context::new();
ctx.add_fact(Fact::new(ContextKey::Seeds, "input", "Start")).unwrap();
let result = engine.run(ctx).expect("should converge");
println!("Converged in {} cycles", result.cycles);
}
The shared, typed, evolving state of a job.
pub struct Context {
// Internally organized by ContextKey
// Seeds → Signals → Hypotheses → Strategies → Evaluations
}
pub enum ContextKey {
Seeds, // Initial input data
Signals, // Observations and discoveries
Hypotheses, // Tentative conclusions
Strategies, // Proposed solutions
Evaluations, // Quality assessments
Constraints, // Domain constraints
Proposals, // Pending LLM suggestions
Approvals, // Human-approved items
}
A capability that reads context and emits effects.
pub trait Agent: Send + Sync {
/// Unique name for this agent
fn name(&self) -> &str;
/// Context keys this agent depends on
fn dependencies(&self) -> &[ContextKey];
/// Whether this agent should run given current context
fn accepts(&self, ctx: &Context) -> bool;
/// Execute and return effects (facts to add)
fn execute(&self, ctx: &Context) -> AgentEffect;
}
Buffered output from an agent. Never mutates context directly.
pub struct AgentEffect {
pub facts: Vec<Fact>,
pub proposed_facts: Vec<ProposedFact>,
pub trace: Option<String>,
}
┌─────────────────────────────────────────────────────────────────┐
│ TRUST LEVELS │
├─────────────────────────────────────────────────────────────────┤
│ Fact (authoritative) │ ProposedFact (tentative) │
│ ───────────────────────── │ ───────────────────────────── │
│ Emitted by deterministic │ Emitted by LLM agents │
│ agents or promoted from │ Requires validation before │
│ validated proposals │ becoming a Fact │
│ Added directly to Context │ Held in Proposals key │
└─────────────────────────────────────────────────────────────────┘
The convergence loop that orchestrates agents.
pub struct Engine {
agents: Vec<Box<dyn Agent>>,
invariants: Vec<Box<dyn Invariant>>,
budget: Budget,
}
impl Engine {
/// Run until convergence or budget exhaustion
pub fn run(&self, ctx: Context) -> Result<ConvergeResult, ConvergeError>;
}
All agents must follow this rule:
An agent has contributed if any artifact it emitted exists in the context — regardless of acceptance or validation.
impl Agent for MyAgent {
fn dependencies(&self) -> &[ContextKey] {
// Include BOTH input AND output keys
&[ContextKey::Seeds, ContextKey::Hypotheses]
}
fn accepts(&self, ctx: &Context) -> bool {
// 1. Check precondition
if !ctx.has(ContextKey::Seeds) { return false; }
// 2. Check idempotency (context-based, not hidden state)
let my_prefix = format!("{}-", self.name());
!ctx.get(ContextKey::Hypotheses)
.iter()
.any(|f| f.id.starts_with(&my_prefix))
}
fn execute(&self, _ctx: &Context) -> AgentEffect {
AgentEffect::with_fact(Fact::new(
ContextKey::Hypotheses,
"myagent-result-1",
"derived content",
))
}
}
Runtime constraints that guard correctness.
pub trait Invariant: Send + Sync {
/// Name of this invariant
fn name(&self) -> &str;
/// When to check: Structural, Semantic, or Acceptance
fn class(&self) -> InvariantClass;
/// Check the invariant against current context
fn check(&self, ctx: &Context) -> InvariantResult;
}
pub enum InvariantClass {
/// Checked on every merge (schema, types)
Structural,
/// Checked per-cycle (domain rules)
Semantic,
/// Checked at convergence (success criteria)
Acceptance,
}
Traits for providers to implement.
// LLM completion
pub trait LlmProvider: Send + Sync {
fn name(&self) -> &str;
fn model(&self) -> &str;
fn complete(&self, request: &LlmRequest) -> Result<LlmResponse, LlmError>;
}
// Embeddings
pub trait Embedding: Send + Sync {
fn embed(&self, request: &EmbedRequest) -> Result<EmbedResponse, CapabilityError>;
}
// Vector similarity search
pub trait VectorRecall: Send + Sync {
fn query(&self, query: &VectorQuery) -> Result<Vec<VectorMatch>, CapabilityError>;
}
// Graph pattern matching
pub trait GraphRecall: Send + Sync {
fn query(&self, query: &GraphQuery) -> Result<GraphResult, CapabilityError>;
}
// Re-ranking
pub trait Reranking: Send + Sync {
fn rerank(&self, request: &RerankRequest) -> Result<RerankResponse, CapabilityError>;
}
| Guarantee | Mechanism |
|---|---|
| Determinism | Agents sorted by name; effects merged in order |
| Termination | Budget limits cycles, facts, and wall-clock time |
| Isolation | Agents read-only context; effects buffered |
| Auditability | Every fact has provenance |
| Correctness | Invariants block invalid states |
repeat
1. Determine eligible agents (accepts() == true)
2. Execute eligible agents in parallel (read-only context)
3. Collect AgentEffects (buffered)
4. Merge effects into context (serialized, deterministic order)
5. Check structural invariants (immediate)
6. Check semantic invariants (per-cycle)
until
Context unchanged (convergence) OR
Budget exhausted OR
Invariant failed
finally
Check acceptance invariants (convergence gate)
# Run all convergence axiom tests
cargo test -p converge-core --test engine_convergence_axioms -- --nocapture
# Run all tests
cargo test -p converge-core
# Run property-based tests
cargo test -p converge-core --test property_tests
| Test File | What It Tests |
|---|---|
engine_convergence_axioms |
Core convergence guarantees |
convergence |
Basic convergence behavior |
parallel_execution |
Parallel agent execution |
transparent_determinism |
Determinism guarantees |
hitl_pause_resume_axioms |
Human-in-the-loop flows |
property_tests |
Property-based testing |
See docs/ for detailed documentation:
This crate is part of the Converge project.
Standalone repo: github.com/kpernyer/converge-core
Proprietary (Aprio One AB)