plungeai-missions
Missions — bounded autonomous agent runs (type: harness)
A mission bounds what an agent may do for ONE goal: a standing purpose, a fenced tool set, an iteration cap, optional identity/knowledge injection, and self-checked success criteria.
A mission bounds what an agent may do for ONE goal: a standing purpose, a fenced
tool set, an iteration cap, optional identity/knowledge injection, and self-checked
success criteria. You give a goal; the platform runs a real ReAct tool loop
(think → tool call → result → …) against it, hard-stopped at every bound. This is
the capability to reach for when the steps are NOT known in advance — one harness
task, not a chain of guessed small tasks.
Missions are humans-and-workflows-in-control by construction: the agent executes inside the bounds; it cannot widen them.
Minimal and typical
name: Claim verification
tasks:
- type: harness
goal: "Verify the claims in {input} and produce a sourced verdict"
mission: |
You are a careful researcher. Verify claims against primary sources.
Refuse to conclude beyond the evidence.
skills: [research]
effort: standard
allowed_tools: [web_search, web_fetch, task_complete]
success_criteria:
- Every verdict cites at least one primary sourceOr from an agent context, without YAML — but note the MCP tool accepts only a subset of the mission contract:
plungeai_run_mission {goal, mission?, allowed_tools?, max_iterations? (≤50),
success_criteria?, persona?, skills?, mode?: "sync"|"async"}Those are ALL the fields. Anything beyond them — experts, backgrounds,
plugins, mcp, model/provider, effort, max_parallel, permissions,
memory_owner, local — requires authoring a one-task type: harness workflow
(the full table below) and running it via plungeai_execute_workflow.
Defaults to async — poll plungeai_get_workflow_status, fetch with
plungeai_get_result. The run recalls and writes long-term memory automatically
(see plungeai-memory). If status reports ⏸ AWAITING USER APPROVAL or
AWAITING USER, relay it and continue with plungeai_continue after the user
decides.
The authoring contract — flat peers, one internal shape
Capability fields are written FLAT on the task (the engine folds them into the
mission internally). The nested mission: { … } object form also works; flat wins
per key over nested.
Full field reference
| Field | Type | What it bounds |
|---|---|---|
goal | string | The per-run input — becomes the agent's prompt |
mission | multi-line string | Standing purpose → system-prompt frame. A SINGLE-TOKEN string is a card reference instead (below) |
persona | string | One voice per run (digital_twin alias; personas: [x] → first entry) |
skills | string[] | Instruction packs — first 5 eager, rest on demand (plungeai-skills-plugins) |
experts | string[] | Domain lenses — first 3 eager (plungeai-skills-plugins) |
backgrounds | string[] | Ambient context cards — first 3 eager, injected first |
plugins | string[] | Bundles: skill index + MCP servers + scripts (plungeai-skills-plugins) |
mcp | string[] | MCP server ids connected in-loop |
model, provider | string | Model/provider override (plungeai-models) |
effort | quick|standard|deep | Turn-budget preset: 4 / 12 / 20 turns |
max_turns | number | Explicit loop cap (alias max_iterations); wins over effort; runtime default 50 |
max_tokens | number | Per-turn OUTPUT token budget for the loop's model calls (runtime default 16384) |
budget_usd_run | number | Per-run spend cap in USD — the loop prices its running token cost each turn and stops (stopReason: "budget") once exceeded; absent = no cap |
max_parallel | number | Widest fan-out one delegate call may spawn — cap-and-refuse, never silently batched |
allowed_tools | string[] | The tool fence (below) |
allowed_agents | string[] | 'all' | Agent fence for call_agent |
denied_agents | string[] | Subtracted from the agent fence |
permissions | map tool → allow|ask|deny | Per-tool human gate: ask pauses the run with needs_approval before the tool executes; deny rejects the call. Keys may be tool names or permission classes (send|write|pay|delete) |
permission_locks | string[] | Admin-locked permission classes: a class listed here forces its allow up to ask, so a bot author's own allow cannot silently auto-run it. Sourced from the DB at the Studio execute boundary, not trusted from raw YAML for enforcement — carried through, not authored |
success_criteria | string[] | Self-checked statements the agent verifies before finishing |
instructions | string | Extra author instructions, appended after skills — always lands |
python_executor | auto|pyodide|anthropic|gemini | run_python tier routing |
memory_owner | string | Memory namespace override — do not use; omit entirely (policy since 2026-08-23). Identity does not belong in mission YAML: ownership lives on the workflow row and runtime identity is injected per run; a hardcoded id that isn't the runner's own is rejected by the harness guard anyway. See plungeai-memory and orchestration/BOT-CREATION.md |
local, local_agents | bool, string[] | Local bot: actions route to the user's own machine via the desktop daemon (cloud brain, local hands); requires a connected local node |
The tool fence
allowed_tools is a hard whitelist — only listed tools ever reach the LLM; an
out-of-fence call is refused by the runtime, not merely discouraged. Omit it and the
loop runtime applies its own fail-closed default fence.
The full loop-tool catalog (fence vocabulary): read_file, write_file,
edit_file, list_files, search_files, delete_file, web_search, web_fetch,
load_skill, memory, knowledge, skill_manage, recall, recall_history,
delegate, local_agent, registry_search, registry_lookup, call_agent,
invoke_workflow, run_python, ask_user, platform_action, task_complete.
Fence design rules:
- Always include
task_complete— it is how a run ends cleanly. - Smallest set that can achieve the goal. A verification mission needs
web_search, web_fetch, task_complete— not the file tools. ask_userkeeps human-question continuations available on every surface; include it when the goal may need clarification mid-run.- Two loop runtimes exist: the default full-surface runtime (all 24 tools; in
unattended runs — the engine/bot default —
platform_actionis stripped from that default fence, which is why a scheduled mission can behave differently from the same mission run interactively) anduniversal-agent(thin default fence: the registry triadregistry_search+registry_lookup+call_agent, plus research +load_skill+ask_user+task_complete— an unfenced universal-agent mission CAN call registry agents) — select withagent:on the harness task. An explicitallowed_toolsalways wins over either default.
The agent fence and money-class protection
call_agent lets the loop invoke registry agents. allowed_agents: [a, b] limits it
to those; 'all' opens the catalog minus denied_agents. Payment/blockchain-class
agents stay deny-unless-explicitly-named even under 'all' — naming them is the
only way a mission can touch money, and permissions: {call_agent: ask} adds a human
gate on top. This is a trust fence: surface refusals, never work around them.
Recursion and fan-out guards
delegatespawns parallel child agents; children get a minimal default tool set and ALWAYS havedelegate,invoke_workflow, andmemorystripped — no fan-out explosions, no child memory writes.- Orchestrator depth is propagated (
depth→ children senddepth+1) and hard-capped (default max depth 3); a too-deep dispatch is refused. max_parallelcaps one delegate call's width by refusal, never by serializing — silent batching would multiply wall clock.
Pre-built agent cards (mission_ref)
A stored agent card (markdown frontmatter + body, compiled by the platform) packages a whole mission for reuse:
- type: harness
goal: "{input}"
mission_ref: research-analyst # canonical; `pack:` is an alias
# equivalent shorthand: mission: research-analyst (single token = card id)A card with no explicit agent: hosts on universal-agent — predict its default
fence (the thin one above) accordingly.
Merge order, per key, last wins: card → workflow root → task. Two rules that bite:
- Arrays REPLACE, never union. Task-level
skills: [x]replaces the card's skill list entirely; an explicitskills: []deliberately clears it. - A blank inline
missiontext does not override the card's purpose; any non-blank inline text does.
Cards are also directly schedulable: plungeai_schedule {action: "create", mission_ref: "…", schedule: "0 7 * * *", …} (plungeai-scheduling).
Memory lifecycle
At run start the engine recalls the owner's long-term memory as a frozen
snapshot prepended to the system prompt; the loop's memory tool writes back
durably (writes do not mutate the running prompt). Bots do not set
memory_owner — policy since 2026-08-23 is to omit it entirely; a bot run reads
and writes the owner's general memory namespace, shared across all their bots and
runs (a hardcoded per-bot value is rejected by the harness guard unless it names
the runner's own identity, so it is redundant at best). Scheduled user runs keep
the full memory lifecycle; only system/heartbeat jobs run memory-free. Details,
limits, threat-scanning, and the bot-memory policy: plungeai-memory.
Execution semantics worth engraving
- No per-task
retryon harness. Mission runs are not idempotent — the engine never re-fires them automatically, and neither should you without checking what the first run already did (plungeai_executions). success_criteriaare self-checked by the agent (no external verifier in the loop) — write them as verifiable statements, and treat them as guidance-grade, not proof.- Runs pause (never die) on
ask_userquestions andpermissions: askgates — status carries acontinuationblock; resume withplungeai_continue(messagefor answers,approve: trueonly after an explicit human yes). - Budget honestly:
quick(4 turns) suits a lookup-and-answer;deep(20) a real investigation; explicitmax_turnsfor anything unusual. A run that hits its cap ends with whatever it has — better a tight cap and a follow-up mission than an unbounded loop.
Mission vs workflow — the decision
| Signal | Choose |
|---|---|
| Steps enumerable in advance, repeatable | Workflow of plain tasks (plungeai-workflows) |
| Open-ended goal, tool choice needs judgment | ONE harness mission |
| Both: fixed pipeline with one judgment-heavy stage | Workflow with a single embedded type: harness task |
The classic failure is decomposing an open-ended goal into six guessed tasks — the guesses are wrong and the pipeline is brittle. Give the goal to one fenced mission instead.
MCP tool: plungeai_run_mission
Purpose: run a bounded autonomous agent mission — a loop agent with a
goal, a tool fence, and an iteration cap. It recalls and writes the user's
long-term memory automatically. Async by default (missions are long);
pass mode: "sync" only for short, tightly-bounded goals.
Parameters
| Param | Type | Notes |
|---|---|---|
goal | string ≤65536, required | What to achieve. |
mission | string | The mission brief / operating instructions (default: a capable general agent that cites sources). |
allowed_tools | string[] ≤50 | The tool fence (default web_search, web_fetch, task_complete). The agent cannot use tools outside it. |
max_iterations | int 1–50 | Loop cap (default 8). |
success_criteria | string[] ≤20 | Explicit done-conditions. |
persona | string | Persona id to inject. |
skills | string[] ≤20 | Skill ids to inject. |
mode | sync | async | Default async. |
Example
{"user_request": "research the EU AI Act's impact on medical devices",
"goal": "Produce a sourced brief on how the EU AI Act affects medical-device software vendors",
"max_iterations": 12,
"success_criteria": ["cites primary sources", "covers timelines and penalties"]}Returns (async): "Started mission <id> (async). Poll
plungeai_get_workflow_status with this id, then fetch output with
plungeai_get_result once completed. The agent recalls and writes long-term
memory automatically. If the status reports ⏸ AWAITING USER APPROVAL or
AWAITING USER, relay it to the user and continue with plungeai_continue." —
follow that script. Sync mode returns the finished result (or a ⏸ pause)
directly.
Failures & fixes: timeouts in sync mode → go async (the remediation says so). A mission's own tool failures are the agent's to work around inside its loop; the envelope classifies anything terminal. Note: async runs emit no progress notifications — poll for status instead of waiting for a stream.