Skip to main content

What Are Agents?

In OpenFang, an agent is an autonomous execution unit with:
  • A unique identity (AgentId — UUID v4)
  • A manifest declaring capabilities, tools, model config, and resources
  • A session containing conversation history and memory
  • A module (builtin:chat, wasm:module.wasm, python:script.py)
  • A capability set enforced at the kernel level
Agents can:
  • Respond to user messages
  • Execute tool calls (file I/O, web search, shell commands, etc.)
  • Spawn child agents
  • Send messages to other agents
  • Store and recall memories
  • Run on schedules (continuous, periodic, proactive)

Agent Manifest Format

Every agent is defined by an AgentManifest (TOML or JSON):
agent.toml
# Basic metadata
name = "researcher"
version = "0.1.0"
description = "Deep research agent with credibility checking"
author = "OpenFang"
module = "builtin:chat"

# Scheduling mode
[schedule]
mode = "reactive"  # reactive | continuous | periodic | proactive

# Model configuration
[model]
provider = "anthropic"
model = "claude-sonnet-4-20250514"
api_key_env = "ANTHROPIC_API_KEY"
max_tokens = 8192
temperature = 0.7

# Fallback models (tried in order if primary fails)
[[fallback_models]]
provider = "openai"
model = "gpt-4o"
api_key_env = "OPENAI_API_KEY"

[[fallback_models]]
provider = "groq"
model = "llama-3.3-70b-versatile"
api_key_env = "GROQ_API_KEY"

# Resource quotas
[resources]
max_tokens_per_hour = 1000000
max_cost_per_hour = 10.0
max_iterations = 50

# Priority level (affects scheduling)
priority = "normal"  # low | normal | high | critical

# Capability grants
[capabilities]
tools = ["web_search", "web_fetch", "file_read", "file_list", "memory_store", "memory_recall"]
memory_read = ["*"]
memory_write = ["self.*"]
network = ["*.wikipedia.org", "*.arxiv.org", "api.openai.com"]
shell = []  # No shell access
agent_spawn = false
agent_message = ["summarizer"]
agent_kill = []

# Tool-specific configuration
[tools.web_search]
provider = "tavily"
max_results = 10

[tools.web_fetch]
timeout_seconds = 30
max_content_bytes = 500000

# Installed skills (empty = all available)
skills = ["web-search", "pdf-reader", "regex-expert"]

# MCP server allowlist (empty = all connected servers)
mcp_servers = []

# Tags for discovery
tags = ["research", "analysis", "fact-checking"]

# Model routing (auto-select models by complexity)
[routing]
enabled = true
frontier_threshold = 0.8
smart_threshold = 0.5
balanced_threshold = 0.3

# Autonomous agent config (for 24/7 agents)
[autonomous]
approval_required_for = ["file_write", "shell_exec", "agent_spawn"]
max_actions_per_cycle = 100
idle_timeout_seconds = 3600

# Workspace directory
workspace = "~/.openfang/workspaces/researcher"
generate_identity_files = true

# Execution policy override
[exec_policy]
allow_shell = false
allow_network = true
allow_file_write = false

# Tool allowlist (only these tools available)
tool_allowlist = []

# Tool blocklist (excluded after allowlist)
tool_blocklist = ["shell_exec", "docker_exec"]
FieldTypeDefaultDescription
namestring”unnamed”Human-readable agent name
versionstring”0.1.0”Semantic version
descriptionstring""What this agent does
authorstring""Author identifier
modulestring”builtin:chat”Execution module path
scheduleScheduleModereactiveScheduling configuration
modelModelConfigLLM model settings
fallback_modelsVec<FallbackModel>[]Fallback chain
resourcesResourceQuotaToken/cost limits
priorityPrioritynormalScheduling priority
capabilitiesManifestCapabilitiesGranted capabilities
profileOption<ToolProfile>NoneNamed tool profile
toolsHashMap<String, ToolConfig>Tool-specific configs
skillsVec<String>[]Skill allowlist (empty = all)
mcp_serversVec<String>[]MCP server allowlist
metadataHashMap<String, Value>Custom metadata
tagsVec<String>[]Discovery tags
routingOption<ModelRoutingConfig>NoneAuto-model selection
autonomousOption<AutonomousConfig>NoneGuardrails for 24/7 agents
workspaceOption<PathBuf>NoneWorkspace directory
exec_policyOption<ExecPolicy>NonePer-agent policy override
tool_allowlistVec<String>[]Tool allowlist
tool_blocklistVec<String>[]Tool blocklist

Agent Lifecycle States

Agent is active and can receive messages. All subsystems are initialized:
  • Session loaded from memory
  • Capabilities granted
  • Quota tracking active
  • Event subscriptions registered
  • Background loops started (if continuous/periodic/proactive)
Agent is paused (e.g., during daemon shutdown). State persisted to SQLite:
  • Session saved
  • Quota counters saved
  • Background loops stopped
  • Event subscriptions removed
On reboot, agents transition back to Running automatically.
Agent has been killed. Removed from:
  • AgentRegistry
  • CapabilityManager
  • AgentScheduler
  • EventBus subscriptions
  • TriggerEngine
  • Persistent storage (SQLite)
Sessions are cascade-deleted. This is irreversible.

Spawn Flow

When you spawn a new agent:
1. Generate AgentId (UUID v4) and SessionId
2. Create session in memory substrate
3. Parse manifest and extract capabilities
4. Validate capability inheritance
   ↳ Child cannot have more capabilities than parent
5. Grant capabilities via CapabilityManager
6. Register with AgentScheduler (quota tracking)
7. Create AgentEntry and register in AgentRegistry
8. Persist to SQLite via memory.save_agent()
9. If agent has parent, update parent's children list
10. Register proactive triggers (if schedule.mode = "proactive")
11. Publish Lifecycle::Spawned event
12. Evaluate triggers
Code reference: crates/openfang-kernel/src/kernel.rs:spawn_agent()
Spawn time: ~5ms on M1 Pro (2021). Includes full capability validation and SQLite persistence.

Capability Inheritance Validation

When an agent spawns a child, inheritance validation prevents privilege escalation:
use openfang_types::capability::{Capability, validate_capability_inheritance};

let parent_caps = vec![
    Capability::FileRead("/data/*".to_string()),
    Capability::NetConnect("api.example.com".to_string()),
];

let child_caps = vec![
    Capability::FileRead("/data/reports/*".to_string()),  // ✅ Subset of parent
    Capability::ShellExec("*".to_string()),                // ❌ Not granted to parent
];

// This will return Err — child cannot have ShellExec
validate_capability_inheritance(&parent_caps, &child_caps)?;
Code reference: crates/openfang-types/src/capability.rs:validate_capability_inheritance()

Message Flow

When you send a message to an agent:
1. RBAC check
   AuthManager resolves channel identity and checks user role permissions

2. Channel policy check
   ChannelBridgeHandle.authorize_channel_user() enforces DM/group policy

3. Quota check
   AgentScheduler verifies agent hasn't exceeded token-per-hour limit

4. Entry lookup
   Fetch AgentEntry from registry

5. Module dispatch
   Based on manifest.module:
   - builtin:chat → LLM agent loop
   - wasm:path/to/module.wasm → WASM sandbox execution
   - python:path/to/script.py → Python subprocess execution

6. LLM agent loop (for builtin:chat)
   a. Load or create session from memory
   b. Load canonical context summary (cross-channel memory)
   c. Append stability guidelines to system prompt
   d. Resolve LLM driver (per-agent override or kernel default)
   e. Gather available tools (filtered by capabilities + skills + MCP)
   f. Initialize loop guard (tool loop detection)
   g. Run session repair (validate message history)
   h. Run iterative loop: send → LLM → tool calls → results
   i. Auto-compact session if threshold exceeded
   j. Save updated session and canonical session

7. Cost estimation
   MeteringEngine.estimate_cost_with_catalog() computes cost in USD

8. Record usage
   Update quota tracking with token counts
   Persist usage event to SQLite

9. Return result
   AgentLoopResult with response text, token usage, iterations, cost_usd
Code reference:
  • crates/openfang-kernel/src/kernel.rs:send_message()
  • crates/openfang-runtime/src/agent_loop.rs:run_agent_loop()
Message dispatch time: ~10ms (RBAC + quota check + routing). LLM latency is additional.

Capabilities System

OpenFang uses capability-based security: an agent can only perform actions it has been explicitly granted permission to do.

Capability Types

pub enum Capability {
    // File system
    FileRead(String),           // Read files matching glob pattern
    FileWrite(String),          // Write files matching glob pattern

    // Network
    NetConnect(String),         // Connect to hosts matching pattern
    NetListen(u16),             // Listen on specific port

    // Tools
    ToolInvoke(String),         // Invoke specific tool by ID
    ToolAll,                    // Invoke any tool (dangerous)

    // LLM
    LlmQuery(String),           // Query models matching pattern
    LlmMaxTokens(u64),          // Token budget cap

    // Agent interaction
    AgentSpawn,                 // Can spawn sub-agents
    AgentMessage(String),       // Can message agents matching pattern
    AgentKill(String),          // Can kill agents matching pattern

    // Memory
    MemoryRead(String),         // Read from memory scopes
    MemoryWrite(String),        // Write to memory scopes

    // Shell
    ShellExec(String),          // Execute shell commands
    EnvRead(String),            // Read environment variables

    // OFP (peer-to-peer)
    OfpDiscover,                // Can discover remote agents
    OfpConnect(String),         // Can connect to peers
    OfpAdvertise,               // Can advertise services

    // Economic
    EconSpend(f64),             // Can spend up to amount in USD
    EconEarn,                   // Can accept payments
    EconTransfer(String),       // Can transfer funds to agents
}
Code reference: crates/openfang-types/src/capability.rs

Pattern Matching Rules

PatternMatchesExample
Exact matchExact string"api.openai.com:443" matches "api.openai.com:443"
Wildcard *Anything"*" matches any host
Suffix wildcardEnds with"*.openai.com:443" matches "api.openai.com:443"
Prefix wildcardStarts with"/data/*" matches "/data/reports/q4.json"
Middle wildcardContains"api.*.com" matches "api.openai.com"

Enforcement Flow

Code reference:
  • crates/openfang-kernel/src/capabilities.rs
  • crates/openfang-runtime/src/tool_runner.rs

Security by Default

Capabilities are deny-by-default: if not explicitly granted, the operation is blocked. The LLM never sees tools it can’t invoke — they’re filtered out before the request.

Spawning and Messaging

Spawn a Child Agent

Agents can spawn children if they have AgentSpawn capability:
[capabilities]
agent_spawn = true
From the parent agent’s LLM:
I need to analyze these logs in parallel. Let me spawn a log-analyzer agent.

&lt;tool_use&gt;
  <tool_name>agent_spawn</tool_name>
  &lt;parameters&gt;
    &lt;manifest&gt;
      name = "log-analyzer"
      description = "Analyzes application logs for errors"
      module = "builtin:chat"
      [model]
      provider = "groq"
      model = "llama-3.3-70b-versatile"
      [capabilities]
      tools = ["file_read", "memory_store"]
      memory_write = ["self.*"]
    &lt;/manifest&gt;
  &lt;/parameters&gt;
&lt;/tool_use&gt;
The kernel will:
  1. Parse the manifest
  2. Validate that child capabilities ⊆ parent capabilities
  3. Spawn the agent if valid
  4. Return the new AgentId

Send a Message to Another Agent

Agents can message others if they have AgentMessage(pattern) capability:
[capabilities]
agent_message = ["summarizer", "translator"]
From the LLM:
I've completed the research. Let me send the report to the summarizer agent.

&lt;tool_use&gt;
  <tool_name>agent_message</tool_name>
  &lt;parameters&gt;
    <target_agent_name>summarizer</target_agent_name>
    <message>Please summarize this 50-page research report into 3 key findings...</message>
  &lt;/parameters&gt;
&lt;/tool_use&gt;
The kernel will:
  1. Check AgentMessage("summarizer") capability
  2. Resolve summarizer to an AgentId
  3. Route the message
  4. Return the response
Code reference: crates/openfang-runtime/src/tool_runner.rs:agent_message()
Inter-agent depth limit: 5 levels maximum. Prevents unbounded recursive agent-to-agent calls.

Scheduling Modes

Agents can run in four modes:
Default mode. Agent only runs when it receives a message. No background loop.
[schedule]
mode = "reactive"
Use cases: Chatbots, on-demand assistants, API endpoints
Agent runs in a continuous loop, waking up periodically to check for work.
[schedule]
mode = "continuous"
interval_seconds = 60
Use cases: Monitoring, data ingestion, alerting
Agent runs on a cron-like schedule.
[schedule]
mode = "periodic"
cron = "0 9 * * *"  # Every day at 9 AM
Use cases: Daily reports, scheduled data processing, backups
Agent runs in response to system events (triggers).
[schedule]
mode = "proactive"

[[schedule.triggers]]
event = "file_created"
pattern = "/data/inbox/*.json"
Use cases: Event-driven workflows, reactive automation

Agent Loop Stability

The agent loop includes multiple hardening layers:

Loop Guard

Detects when an agent is stuck calling the same tool with the same parameters.
Warn threshold (default 3): Logs warning + injects hint to LLM
Block threshold (default 5): Refuses tool call + returns error
Circuit breaker (default 30): Terminates agent loop entirely
Uses SHA256 hashing of (tool_name, params) to identify repetition. Code reference: crates/openfang-runtime/src/loop_guard.rs

Session Repair

7-phase validation runs before each agent loop iteration:
  1. Drop orphaned ToolResult messages (no matching ToolUse)
  2. Remove empty messages
  3. Merge consecutive same-role messages
  4. Validate content blocks
  5. Fix missing tool_use_id references
  6. Ensure alternating user/assistant pattern
  7. Truncate if exceeds context window
Code reference: crates/openfang-runtime/src/session_repair.rs

Tool Result Truncation

Enforces a 50,000 character hard cap on tool output. Truncated results include a marker showing original size:
[Output truncated: 125,432 bytes → 50,000 bytes]

Tool Timeout

All tool executions are wrapped in a 60-second timeout. Tools that exceed this return a timeout error to the LLM instead of hanging.

Max Continuations

MAX_CONTINUATIONS = 3 prevents infinite “Please continue” loops.

Stability Guidelines

Appended to every agent’s system prompt:
STABILITY GUIDELINES
- If a tool call fails twice, try a different approach
- If you're repeating the same action, stop and reflect
- If you're unsure, ask the user instead of guessing
- If a task is blocked, report the blocker clearly
- Never retry the same failed operation more than 3 times
Code reference: crates/openfang-runtime/src/agent_loop.rs

Next Steps

Memory System

Learn about the 6-layer memory substrate

Hands System

Explore autonomous capability packages

Security Model

Understand capability-based security

Spawn Your First Agent

Step-by-step guide to creating an agent

Build docs developers (and LLMs) love