Skip to content

Repository files navigation

cortex-toml

Configuration-as-code for the Exocortex — parse, validate, serialize, diff, and migrate .cortex.toml files

crates.iodocs.rslicense

What is Cortex TOML?

Every Exocortex deployment needs configuration — agent definitions, memory settings, network parameters, and more. cortex-toml is the library that makes .cortex.toml files first-class configuration artifacts: typed, validated, versionable, and diffable.

Think of it as the Cargo.toml parser for the Exocortex ecosystem. Just as serde + toml give Rust projects typed configuration, cortex-toml gives Exocortex deployments:

  • Parsing: TOML string → typed CortexConfig struct (via serde)
  • Validation: Check types, ranges, required fields, and cross-field constraints
  • Serialization: CortexConfig → pretty-printed TOML
  • Diffing: Compare two configs and generate a human-readable migration plan
  • Round-tripping: Parse → serialize → parse produces identical results

Why Does This Matter?

Configuration-as-code is a DevOps best practice that brings software engineering rigor to infrastructure:

  • Version control: Track configuration changes in git, review them in PRs, roll back when needed
  • Validation: Catch misconfigurations (bad ports, impossible temperatures, missing fields) before deployment
  • Diffing: See exactly what changed between two config versions — essential for change management
  • Migration planning: Generate actionable migration steps when upgrading configurations
  • Type safety: The CortexConfig struct is your schema — no silent field name typos or wrong types

Real-world applications:

  • CI/CD pipelines: Validate .cortex.toml in CI before deploying
  • Config drift detection: Diff running config against committed config to detect unauthorized changes
  • Multi-environment management: Compare dev/staging/prod configs to ensure consistency
  • Agent onboarding: New agents get validated configuration from day one

Architecture

┌──────────────────────────────────────────────────────────────┐
│ Cortex TOML Pipeline │
│ │
│ .cortex.toml │
│ ┌───────────────────────┐ │
│ │ name = "my-exocortex" │ │
│ │ version = "0.1.0" │ TomlParser │
│ │ │ ──▶ parse(input) ──▶ CortexConfig │
│ │ [agents.main] │ │
│ │ type = "chat" │ ┌────────────────────────┐ │
│ │ model = "gpt-4" │ │ CortexConfig │ │
│ │ │ │ ├─ name: String │ │
│ │ [memory] │ │ ├─ version: String │ │
│ │ backend = "sqlite" │ │ ├─ agents: HashMap │ │
│ │ max_entries = 5000 │ │ ├─ memory: MemoryCfg │ │
│ │ │ │ └─ network: NetworkCfg│ │
│ │ [network] │ └────────┬───────────────┘ │
│ │ bind = "0.0.0.0" │ │ │
│ │ port = 3000 │ ▼ │
│ │ tls = true │ ConfigValidator │
│ └───────────────────────┘ ┌────────────────────┐ │
│ │ name non-empty? │ │
│ │ temperature 0–2? │ │
│ │ port > 0? │ │
│ │ decay 0–1? │ │
│ └────────┬───────────┘ │
│ │ │
│ TomlSerializer ▼ │
│ serialize(config)──▶ TOML ConfigDiff │
│ diff(old, new)──▶ plan │
│ ┌────────────────────┐ │
│ │ - port: 8080 → 3000│ │
│ │ - agents.x: added │ │
│ └────────────────────┘ │
└──────────────────────────────────────────────────────────────┘

Quick Start

use cortex_toml::{TomlParser,ConfigValidator,TomlSerializer,CortexConfig};// Parse a .cortex.toml filelet toml = r#"name = "my-exocortex"version = "0.1.0"[agents.main]type = "chat"model = "gpt-4"temperature = 0.7[memory]backend = "sqlite"max_entries = 5000decay_factor = 0.9[network]bind = "0.0.0.0"port = 3000tls = true"#;let config = TomlParser::parse(toml).expect("Valid TOML");println!("Project: {} v{}", config.name, config.version);println!("Agents: {:?}", config.agents.keys().collect::<Vec<_>>());// Validate the configurationlet errors = ConfigValidator::validate(&config);if errors.is_empty(){println!("✓ Configuration is valid");}else{for err in&errors {println!("✗ {}: {}", err.field, err.message);}}

Serialization and Round-Tripping

// Serialize back to TOMLlet output = TomlSerializer::serialize(&config).unwrap();println!("{}", output);// Round-trip: parse → serialize → parse should be identicallet reparsed = TomlParser::parse(&output).unwrap();assert_eq!(config, reparsed);

Diffing Configurations

use cortex_toml::{ConfigDiff,CortexConfig};let old_config = TomlParser::parse(r#"name = "my-exocortex"version = "0.1.0""#).unwrap();let new_config = TomlParser::parse(r#"name = "my-exocortex"version = "0.2.0"[agents.helper]type = "tool"model = "gpt-3.5""#).unwrap();let diff = ConfigDiff::diff(&old_config,&new_config);if diff.is_empty(){println!("No changes");}else{println!("Migration plan:");println!("{}", diff.migration_plan());// Output:// - version: 0.1.0 → 0.2.0// - agents.helper: absent → added}

Validation Error Handling

use cortex_toml::{TomlParser,ConfigValidator};let bad_config = TomlParser::parse(r#"name = " "[agents.main]type = ""temperature = 5.0"#).unwrap();let errors = ConfigValidator::validate(&bad_config);assert!(!errors.is_empty());// errors[0]: name is required (whitespace only)// errors[1]: agents.main.type is required (empty)// errors[2]: agents.main.temperature must be 0.0-2.0, got 5.0

API Reference

TomlParser

MethodReturnsDescription
TomlParser::parse(input)Result<CortexConfig, String>Parse TOML string to config

TomlSerializer

MethodReturnsDescription
TomlSerializer::serialize(config)Result<String, String>Serialize config to pretty TOML

ConfigValidator

MethodReturnsDescription
ConfigValidator::validate(config)Vec<ValidationError>All validation errors
ConfigValidator::is_valid(config)boolQuick validity check

ConfigDiff

MethodReturnsDescription
ConfigDiff::diff(old, new)ConfigDiffCompute differences between configs
diff.len()usizeNumber of changed fields
diff.is_empty()boolNo changes detected
diff.migration_plan()StringHuman-readable change summary

CortexConfig Structure

FieldTypeDefaultDescription
nameStringrequiredProject name
versionString""Semantic version
agentsHashMap<String, AgentConfig>emptyAgent definitions
memoryMemoryConfigsee defaultsMemory subsystem
networkNetworkConfigsee defaultsNetwork settings

AgentConfig

FieldTypeDefaultDescription
agent_typeStringrequiredAgent type (chat, tool, etc.)
modelString""Model identifier
temperaturef640.7Sampling temperature (0.0–2.0)

MemoryConfig

FieldTypeDefaultDescription
backendString"file"Storage backend
max_entriesu6410000Maximum memory entries
decay_factorf640.95Memory decay rate (0.0–1.0)

NetworkConfig

FieldTypeDefaultDescription
bindString"127.0.0.1"Bind address
portu168080Port number
tlsboolfalseEnable TLS

Mathematical Background

Configuration Diffing as Graph Isomorphism

Diffing two configurations is equivalent to computing the symmetric difference of two labeled graphs. Each config is a tree (TOML is a tree-structured format), and the diff identifies:

  • Changed leaves: Scalar values that differ
  • Added subtrees: New agents or sections present only in the new config
  • Removed subtrees: Sections present only in the old config

The diff algorithm runs in O(n) time where n is the total number of fields in both configs.

Validation as Constraint Satisfaction

Each validation rule is a constraint on a field:

name: non-empty ∧ trim(name) ≠ ""
temperature: 0.0 ≤ value ≤ 2.0
max_entries: value > 0
decay_factor: 0.0 ≤ value ≤ 1.0
port: 0 < value ≤ 65535

The validator applies all constraints independently and returns the full set of violations (not just the first one), enabling batch error reporting.

Decay Factor and Half-Life

The decay_factor in memory configuration controls exponential decay:

retention(n) = decay_factorⁿ
half_life = −ln(2) / ln(decay_factor)
decay_factorHalf-life (writes)
0.9969
0.9513.5
0.906.6
0.854.3

Installation

cargo add cortex-toml

Or add to your Cargo.toml:

[dependencies]
cortex-toml = "0.1.0"

Related Crates

License

MIT © SuperInstance


Part of the Exocortex project — persistent cognitive substrate for multi-agent systems.

About

Rust crate: cortex-toml

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages