Agent capabilities: how they’re built and used

This doc describes how agent capabilities are defined, set, validated, and used so you can extend or add new ones. For setting up and using agents (project init, CLI, HTTP server, DAL APIs, molds, evolve), see guides/AGENT_SETUP_AND_USAGE.md.


1. Where capabilities live

Place Purpose
AgentConfig.capabilities Per-agent list of capability strings (stored on the agent context).
builtin_capabilities(AgentType) (Rust) Default list per type used when no registry override exists.
CAPABILITY_REGISTRY (Rust) Optional override: per–agent-type list used by validation instead of built-ins.
Mold agent.capabilities Capabilities for agents spawned from that mold.
DAL agent block / create_agent_config Capabilities supplied from DAL (agent declaration or config map).

2. How capabilities get set (the “build” process)

A. At spawn time (Rust: agent::spawn)

  1. AgentConfig::new(name, agent_type) creates config with capabilities: Vec::new().
  2. initialize_<type>_agent(agent_context) is called and overwrites agent_context.config.capabilities with the type-specific list (see table below).

So by default, every spawned agent gets the list from the initializer for its type. No separate “registration” step is required for these defaults.

B. Overriding from config (before or instead of init)

So “building out” capabilities for an agent means: either rely on the built-in list for that type, or set/override via config (Rust builder, mold, or DAL config/agent block).


3. Built-in lists (current defaults)

Defined in src/stdlib/agent.rs:

Validation uses either the registry (if set) or builtin_capabilities; it does not read the per-agent AgentContext.config.capabilities — it only checks that the agent type has the required capabilities in the registry/built-in list.


4. Validation vs runtime checks

So:


5. How to add or extend capabilities (concrete steps)

Option A: Add a new capability to an existing type (built-in)

  1. In src/stdlib/agent.rs:
  2. No DAL or mold change required; new agents of that type will get the capability by default, and validate_capabilities will accept it for that type.

Option B: Custom list for a type (registry)

  1. From Rust or from DAL (if you expose it), call agent::register_capabilities(agent_type_string, vec!["cap1", "cap2", ...]).
  2. Validation will use this list instead of builtin_capabilities for that agent_type. Spawn initializers still set config.capabilities per agent; the registry only affects validation.

Option C: Per-agent list (no new built-ins)

  1. Rust: Build config with .with_capabilities(vec!["my_cap", ...]) and spawn. The initializer will overwrite unless you change init to respect existing capabilities (e.g. only set when empty).
  2. Mold: In the mold’s agent block set capabilities: ["my_cap", ...].
  3. DAL: In the agent’s config or agent block, set capabilities to a list of strings.

Then is_capable("my_cap") will be true for that agent; validate_capabilities will only accept it if the type’s built-in/registry list also includes "my_cap" (if you validate that type for that capability).

Option D: New agent type with its own list

  1. Add a new variant to AgentType (e.g. Custom("my_type") or a dedicated variant).
  2. In builtin_capabilities, add a branch returning the new type’s list.
  3. In initialize_<type>_agent (or a new initializer), set agent_context.config.capabilities for the new type.
  4. Wire the new type through spawn/parser/mold as needed so it’s usable from DAL and molds.

6. Summary

To build out agent capabilities you either extend the built-in/init lists and optionally the registry, or supply custom lists per agent via config/mold/DAL; validation and is_capable then reflect those choices.