iron-core 0.1.35

Core AgentIron loop, session state, and tool registry
Documentation

iron-core

iron-core is the core embedding crate for AgentIron.

It provides:

  • the stream-first IronAgent / AgentConnection / AgentSession facade
  • durable messages, timeline entries, and tool-call records
  • tool registration with JSON Schema argument validation
  • approval-gated tool execution
  • ACP-native transports for in-process, stdio, and TCP integrations
  • context compaction, active-context accounting, and handoff export/import
  • layered prompt composition with repository instruction loading and runtime context injection
  • optional embedded Python execution via the embedded-python feature
  • WASM integration plugins via Extism with install lifecycle, manifest extraction, session-scoped enablement, auth-gated tool availability, and a 30-second execution timeout

The facade/runtime API is the supported integration surface.

Requirements

  • Rust 1.95+
  • Tokio for async embedding code

Install

Use the git dependency for now:

[dependencies]
iron-core = { git = "https://github.com/AgentIron/iron-core", branch = "main" }
iron-providers = "0.2.2"
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

iron-core is not ready for crates.io publication yet because the optional embedded-python feature depends on monty from git until a usable crates.io release exists.

If you need the built-in python_exec tool, enable the feature explicitly:

[dependencies]
iron-core = { git = "https://github.com/AgentIron/iron-core", branch = "main", features = ["embedded-python"] }
iron-providers = "0.2.2"
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Quick Start

use iron_core::{Config, FunctionTool, IronAgent, PromptEvent, ToolDefinition};
use iron_providers::{ApiFamily, ProviderConnection, ProviderProfile, RuntimeConfig};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Config::new().with_model("gpt-4o");
    let provider = ProviderConnection::from_profile(
        ProviderProfile::new("openai", ApiFamily::Responses, "https://api.openai.com/v1"),
        RuntimeConfig::new(std::env::var("OPENAI_API_KEY")?),
    )?;
    let agent = IronAgent::new(config, provider);

    agent.register_tool(FunctionTool::new(
        ToolDefinition::new(
            "echo",
            "Return the provided text",
            json!({
                "type": "object",
                "properties": {
                    "text": { "type": "string" }
                },
                "required": ["text"]
            }),
        ),
        |args| Ok(json!({ "echo": args["text"].clone() })),
    ));

    let connection = agent.connect();
    let session = connection.create_session()?;
    let (handle, mut events) = session.prompt_stream("Call echo with hello.");

    while let Some(event) = events.next().await {
        match event {
            PromptEvent::Output { text } => print!("{text}"),
            PromptEvent::ApprovalRequest { call_id, .. } => {
                handle.approve(&call_id).expect("approval should be pending");
            }
            PromptEvent::Complete { outcome } => {
                println!("\nprompt finished: {outcome:?}");
                break;
            }
            _ => {}
        }
    }

    Ok(())
}

The canonical interaction model is stream-first:

  • call session.prompt_stream(...)
  • consume PromptEvents as they arrive
  • use PromptHandle to approve, deny, or cancel an active prompt

Built-In Tools

iron-core can register built-in read, write, edit, glob, grep, and webfetch tools, plus bash or powershell when a shell is available.

Use BuiltinToolConfig to scope filesystem access, disable specific tools, and tune limits such as command timeouts and output caps.

MCP Servers

iron-core supports session-scoped MCP (Model Context Protocol) servers as a tool source alongside built-in and custom tools. The full implementation covers:

  • Runtime-local MCP server inventory with per-server configuration
  • Session-scoped enablement governed by a single runtime-default policy
  • Canonical session-effective tool catalog with precise unavailable-tool diagnostics
  • Approval strategy enforcement for MCP tool calls
  • Transport clients for stdio, HTTP, and HTTP+SSE
  • Connection lifecycle management with single-flight connect guarding
  • Handoff exclusion — MCP state is runtime-local and not portable

Integration Plugins

iron-core includes a WASM-based integration-plugin surface powered by Extism. Plugins are a third tool source alongside built-in tools and MCP servers.

The plugin system is fully implemented:

  • Install lifecycle — fetch (local or HTTPS+checksum), cache, manifest extraction from WASM binaries, identity validation, and Extism-backed WASM host loading
  • WASM execution — tools are invoked via tool_{name} exports with a JSON request/response envelope and a 30-second timeout
  • Session-scoped enablement — runtime-level defaults materialised at session creation, with per-session overrides
  • Canonical tool availability — single-source-of-truth compute_tool_availability() gates tools on health, auth requirements, and scope satisfaction
  • Auth model — runtime-governed auth state, credential bindings, and per-tool scope checks
  • Tool diagnostics — structured UnavailableReason variants for actionable error messages
  • Network policy — allowlist, blocklist, and wildcard policies declared in plugin manifests

Development

Install the security tooling if you want to run the same audit check CI reports:

cargo install cargo-audit

Configure the repository pre-commit hook after cloning:

git config core.hooksPath .githooks

The pre-commit hook runs cargo fmt --manifest-path Cargo.toml -- --check when staged Rust files are present. Before opening or updating a pull request, run the same checks CI validates:

cargo build --manifest-path Cargo.toml --all-targets
cargo fmt --manifest-path Cargo.toml -- --check
cargo clippy --manifest-path Cargo.toml --all-targets --all-features -- -D warnings
cargo test --manifest-path Cargo.toml
cargo audit --file Cargo.lock

The local invoke tasks in tasks.py are a convenience layer over these checks:

inv build
inv test
inv security

The Pull Request workflow runs build, format, lint, and test checks on every PR to main. It also runs cargo audit as a non-blocking audit and posts the output as a PR comment.

Merges to main trigger an automatic patch release that bumps Cargo.toml, creates a vX.Y.Z tag, and creates a GitHub release. Publishing to crates.io is skipped until monty is available from crates.io because crates.io rejects manifests containing git dependencies.

Documentation

Build the API docs locally with:

cargo doc -p iron-core --no-deps

License

Licensed under the Apache License, Version 2.0. See LICENSE.