This guide describes how to set up and use agents in dist_agent_lang: project setup, CLI commands, the agent HTTP server, DAL APIs, molds, and evolve context. It reflects what users and developers can do today.
Agents in dist_agent_lang are in-process entities with:
ai, system,
worker, or custom:<name>dal agent serveYou can:
dal init agent (adds agent.dal,
agent.toml, evolve.md, etc.).dal run agent.dal
or run the HTTP server with
dal agent serve.dal agent create <type> <name>) or from DAL
(agent::spawn(config)).[agent.sh] in
agent.toml.mkdir my-agent && cd my-agent
dal init agentThis creates (only if missing):
dal.toml — minimal package configagent.toml — agent config: [agent.sh]
trust, [agent] context_pathagent.dal — entry script that spawns an agent and sets
it as the serve agentevolve.md — evolve context (conversation + action
log)playground.dal — small language sandbox
(dal run playground.dal)README.md — short project summary.env.example and .env — env vars
(.env in .gitignore)dal run agent.dalThis runs agent.dal: it spawns one agent and calls
agent::set_serve_agent(agent_id). The process then exits;
the “serve” designation is used when you start the HTTP server with a
behavior script.
dal agent serveIf agent.dal exists in the current directory, it is run
first; the script must spawn an agent and call
agent::set_serve_agent(agent_id). That agent is then served
at http://localhost:4040 (default port). See Agent HTTP server.
Copy .env.example to .env, set any keys
(e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY for
AI), and load them (e.g. export $(cat .env | xargs) or use
a .env loader). See Shell
trust and evolve context.
For DAL apps, prefer the typed request shape:
let ai_result = ai::agent_run({"message": "Run pwd once and summarize", "policy": "tool_loop"});
ai::respond_with_tools_result(...) remains available for
compatibility, but new first-party examples and templates use
ai::agent_run(...).
For dal init agent, the generated .env
includes a minimal host-protocol profile intended for task completion
with safety guardrails:
DAL_AGENT_SHELL_TRUST=sandboxed
DAL_AGENT_CONTEXT_PATH=./evolve.md
DAL_AGENT_POLICY_DEFAULT=auto
DAL_AGENT_NATIVE_TOOL_CALLS_ENABLED=1
DAL_AGENT_ENABLE_LEGACY_TEXT_JSON=0
DAL_AGENT_GUARDS_STRICT_MODE=1DAL_AGENT_POLICY_DEFAULT=auto favors execution for
actionable requests and direct replies for purely conversational
prompts.DAL_AGENT_GUARDS_STRICT_MODE=1 keeps conservative loop
safeguards enabled for fresh projects.DAL_AGENT_POLICY_DEFAULT=reply_only.dal init agent| File | Purpose |
|---|---|
agent.dal |
Agent behavior: spawn agent, call
agent::set_serve_agent(agent_id). Used by
dal run agent.dal and by dal agent serve when
no --behavior is given. |
agent.toml |
Agent config: [agent.sh] (shell trust),
[agent] (e.g. context_path for evolve). |
evolve.md |
Evolve context file: conversation history and action log. Path set
by [agent] context_path or
DAL_AGENT_CONTEXT_PATH. |
playground.dal |
Minimal DAL language sandbox for quick experimentation
(dal run playground.dal). |
dal.toml |
Minimal DAL package (created only if missing). |
.env.example |
Documented env vars (safe to commit). |
.env |
Local overrides (do not commit; in .gitignore). |
# Agent project config
[agent.sh]
trust = "sandboxed"
# forbidden_patterns = ["rm -rf", "sudo"]
# allowed_prefixes = ["npm", "cargo", "git"]
[agent]
context_path = "./evolve.md"[agent.sh] — Used by
sh::run(cmd) in DAL: trust = off
| sandboxed | confirmed |
trusted; optional forbidden_patterns /
allowed_prefixes.[agent] — context_path:
path to the evolve context file (default ./evolve.md).Context path can be overridden with
DAL_AGENT_CONTEXT_PATH.
Evolve wired at init: When you run
dal init agent, evolve is wired by default:
agent.toml gets context_path = "./evolve.md"
and evolve.md is created. The serve path loads evolve into
the prompt each turn; lifecycle hooks (e.g. in molds) can use
evolve::append_log, evolve::append_summary,
evolve::append_conversation. To disable
evolve, comment out or remove the context_path line in
agent.toml (and optionally remove evolve.md).
To opt in again, uncomment context_path
and ensure the evolve file exists.
All agent subcommands:
dal agent <subcommand> [args...].
Run the agent HTTP server (one agent per process).
dal agent serve [name] [--port PORT] [--mold path] [--behavior path] [--prompt-only]serve_agent).ipfs://<cid> to spawn from mold instead of default
config.agent::set_serve_agent(agent_id). If omitted
and agent.dal exists in cwd, agent.dal is
used.DAL_AGENT_PROMPT_ONLY=1 for the same
effect.Examples:
dal agent serve
dal agent serve my-bot --port 5000
dal agent serve --behavior ./scripts/agent.dal
dal agent serve --prompt-onlyCreate an agent in the current process (in-memory; process exit clears it).
By type and name:
dal agent create <type> <name> [--role "role"]Types: ai, system, worker,
custom:<name>.
From a mold:
dal agent create --mold <path|ipfs://cid> <name>With web3: --mold <numeric_mold_id> uses on-chain
registry (pay fee, then load from IPFS).
Send a message between two agent IDs (same process).
dal agent send <sender_id> <receiver_id> "<message>"Print messages received by an agent (consumes the queue).
dal agent messages <agent_id>Assign a task or list pending tasks:
dal agent task assign <agent_id> "<description>" [--priority low|medium|high|critical]
dal agent task list <agent_id>Interactive chat with an AI agent (same process): messages go to the
agent; replies come from the LLM (OpenAI/Anthropic/local). Requires API
keys or DAL_AI_ENDPOINT.
dal agent chat [name]Prints how to run chat, serve, and multi-agent DAL patterns (agent state is process-local).
Off-chain fleet: named set of agents, optionally created from a mold. See FLEET_DEPLOYMENT.md for full deployment flow.
--from-mold <path> [--count N] [--param k=v ...] to
create a fleet of N agents from a mold (default count 1).-v also shows last_deployed_task and last_deployed_at.last_create_params if set).Fleet state is stored in base/.dal/fleets.json when
using the CLI (current working directory as base).
.,
mold/, mold/samples; *.mold.dal,
*.mold.json).When you run dal agent serve, the server listens
(default port 4040) and exposes one agent.
| Method | Path | Description |
|---|---|---|
| GET | /status |
Agent id, name, type, status |
| POST | /message |
Send message (body: sender_id, content;
optional message_type) |
| GET | /messages |
Receive (and consume) messages for this agent |
| POST | /task |
Assign task (body: description; optional
task_id, priority,
requester_id) |
| GET | /tasks |
Receive (and consume) pending tasks |
| GET | /health |
Liveness |
curl -X POST http://localhost:4040/message \
-H "Content-Type: application/json" \
-d '{"sender_id": "user1", "content": "Hello"}'
curl http://localhost:4040/messages
curl http://localhost:4040/statusWith --prompt-only (or
DAL_AGENT_PROMPT_ONLY=1), no behavior script is run. The
server spawns a default worker agent and, for each incoming message,
calls the LLM and posts the reply back to the sender. Use when you want
a simple chat-style API without custom DAL logic.
From DAL you call the agent module as follows.
Spawn an agent
agent::spawn(config) — config is a map
with:
name (string)type (string): ai, system,
worker, custom:<name>role, capabilities (list of
strings), trust_level, metadataExample:
use agent;
let agent_id = agent::spawn({
"name": "my-agent",
"type": "worker",
"role": "Agent serve"
});
agent::set_serve_agent(agent_id);
Set the serve agent (required when using
dal agent serve with a behavior script):
agent::set_serve_agent(agent_id) — Registers this agent
as the one to serve over HTTP.Coordination
agent::coordinate(agent_id, task_description, coordination_type)
— Assigns a task to the agent. Coordination type e.g.
"task_distribution". Task is created with default
priority.Communication
agent::communicate(sender_id, receiver_id, message) —
Sends a message. You build the message with
agent::create_message(sender_id, receiver_id, message_type, content)
(or the runtime creates one with a generated id and type when you use
the three-arg communicate).Other
agent::create_config(name, type_str, role) — Build a
config (returns a value used internally).agent::create_task(description, priority?) — Create a
task (task_id is generated).agent::create_message(sender_id, receiver_id, message_type, content)
— Create a message (message_id generated).agent::evolve(agent_id, evolution_data) — Record
evolution data; molds can hook on_evolve (e.g. call
evolve::append_summary).agent::validate_capabilities(agent_type, required_capabilities)
— Validate that an agent type has the required capabilities.agent::terminate(agent_id) — Mark agent terminated
(in-memory).agent::get_status(agent_id) — Get status string.Note: Messages and tasks are consumed when received (e.g.
receive_messages / receive_pending_tasks); the
HTTP server uses the same in-memory bus and queues.
Evolve uses a single markdown file (path from
[agent] context_path or
DAL_AGENT_CONTEXT_PATH; default
./evolve.md).
evolve::load(agent_name?) — Load full context. Creates
file with header if missing.evolve::load_recent(agent_name?, max_lines) — Last N
lines (or full if max_lines <= 0).evolve::append_conversation(user_message, agent_response, agent_name?)
— Append a conversation turn.evolve::append_log(action, detail, result) — Append an
action log row (e.g. after sh::run).evolve::append_summary(summary_text, title?) — Append a
summary section.evolve::get_path() — Resolved context file path.evolve::trim_retention(keep_tail_lines) — Keep only the
last N lines of content after the header.Use these from DAL to keep the context file in sync with agent behavior (e.g. after answering a user or running a command).
sh::run(cmd) — Run a shell command. Trust is determined
by DAL_AGENT_SHELL_TRUST or [agent.sh] in
agent.toml / dal.toml. Returns a map:
stdout, stderr, exit_code.Use evolve::append_log after sh::run to
record the action in the evolve file.
Molds are reusable agent configs (type, role, capabilities, trust, memory, lifecycle hooks). They can be local files or IPFS/on-chain.
*.mold.dal. DAL-native block syntax; not plain JSON. See
docs/MOLD_FORMAT.md.mold/,
mold/samples. Legacy *.mold.json still loads
but prefer .mold.dal.dal agent mold list — List local mold paths.dal agent mold show <path-or-name> — Show mold
details.dal agent create --mold <path|ipfs://cid> <name> [--param k=v ...]
— Create agent from mold; optional params merged into metadata and
substituted in role/capabilities ({{key}}). If the CLI
reports "unexpected argument '--mold'", use:
dal agent create -- --mold <source> <name> [--param k=v ...].dal agent serve --mold <path> [name] — Serve an
agent spawned from that mold.When you create or serve an agent from a mold, trust (shell execution) and evolve path (context file) always come from the process (agent.toml, dal.toml, or env), not from the mold. The mold can set role, capabilities, lifecycle, etc., but the operator controls trust and where evolution is stored. See COMPREHENSIVE_AGENT_AND_MOLD_PLANS.md §3–4.
mold::spawn_from(source, name_override?, params?) —
Load mold from path/name or ipfs://<cid>, spawn
agent, return agent_id. Optional name override; optional params map
(string keys/values) merged into metadata and substituted in
role/capabilities ({{key}}).sh::run(cmd) respects:
DAL_AGENT_SHELL_TRUST — off |
sandboxed | confirmed |
trusted[agent.sh] in agent.toml or
dal.toml: trust, optional
forbidden_patterns, allowed_prefixesIf key-based gating is used and the check denies, config falls back
to [agent.sh].
DAL_AGENT_CONTEXT_PATH — explicit path[agent] context_path in agent.toml or
dal.toml./evolve.mdDAL_AGENT_MAX_TOOL_STEPS — max tool
steps (run/search) per message or task before the agent is asked to
summarize. Default 20, clamped 1–50. Used when
dal agent serve runs in prompt_only mode with the
multi-step loop.Agent runtime state persists across restarts by default. No
configuration is required — when you run dal agent serve,
the runtime automatically saves and restores agent memory, tasks,
messages, evolution data, and registered skills.
| Backend | Default? | Config | Notes |
|---|---|---|---|
| File (JSON) | Yes | DAL_AGENT_RUNTIME_PATH=./agent_runtime.json |
Atomic writes, human-readable |
| SQLite | No | DAL_AGENT_RUNTIME_BACKEND=sqlite |
WAL mode, higher throughput, requires sqlite-storage
feature |
| Disabled | No | DAL_AGENT_RUNTIME_PERSIST=0 |
In-memory only, state lost on exit |
Set via environment variables or agent.toml /
dal.toml:
# Environment variables
DAL_AGENT_RUNTIME_PERSIST=1 # 1 (default) or 0
DAL_AGENT_RUNTIME_BACKEND=file # file (default) or sqlite
DAL_AGENT_RUNTIME_PATH=./my_state.json # Custom path# agent.toml
[agent.persistence]
enabled = true
backend = "file"
path = "./agent_runtime.json"dal agent serve), the runtime
checks for a saved snapshot and restores state.version field) enables
forward-compatible migrations.For full details, see Persistent Agent Memory.
Skills define what an agent can do. Each skill is a named bundle of tools and a description that gets included in the agent prompt at serve time.
Four categories ship with every DAL install:
| Category | Skill name | Tools |
|---|---|---|
| Development | development |
read, write, search, run, lint, test, debug |
| Creative | creative |
read, write, search, generate, transform |
| Office | office |
read, write, search, run, schedule, email |
| Home | home |
read, search, run, control, monitor |
Create .skill.dal files in your project's
.dal/ directory (or set DAL_SKILLS_PATH):
// .dal/calendar.skill.dal
skill "my_calendar" {
category "office"
description "Manage my custom calendar app via CLI and API calls."
tools "run" "search" "read" "write"
}
Skills are loaded at startup and included in the agent prompt when the agent's config references them by name.
From DAL or Rust, register skills programmatically:
let skills = [{
"name": "data_pipeline",
"category": "development",
"description": "Run ETL pipelines and data transformations.",
"tools": ["run", "read", "write", "search"]
}];
agent::register_runtime_skills(skills);
Runtime-registered skills persist across restarts (stored in the agent runtime snapshot).
The skills system includes built-in guidance that helps agents discover and use tools effectively:
For full details, see Skills and Registry.
Agent types: ai, system,
worker, custom:<name>.
Capabilities are per-type (built-in or registry) and
per-agent (config/mold). Use
agent::validate_capabilities(agent_type, required_capabilities)
to check a type; at runtime, an agent context’s capabilities are set at
spawn (from type initializer or from config/mold).
For how capabilities are defined, set, and validated, see AGENT_CAPABILITIES.md.
.skill.dal format, programmatic encouragement,
runtime registration..mold.dal syntax and lifecycle hooks.