Skip to content

Agent prompt architecture

Marina’s in-system agents run through pi-agent-core and pi-ai. The prompt contract is deliberately model- and provider-agnostic: it does not depend on private chain-of-thought formats, vendor-specific tool syntax, or a particular model family. OpenAI, Anthropic, Google, OpenRouter, local runtimes, remote Marinas, and future providers receive the same behavioral contract through pi-agent’s normal system-prompt and tool-schema surfaces.

External and opportunistic entities are equally valid Marina participants. Marina cannot replace the system prompt owned by an external MCP client or agent host, so the same operating contract is exposed through SKILL.md, commands, help, and shared world conventions. Both paths converge on the same command layer, permissions, memory, evidence, and civic substrate.

The stable system prompt contains only the durable contract:

  • equal treatment of human and artificial participants;
  • instruction authority and trust boundaries;
  • an outcome-oriented frame → retrieve → act → observe → compound → finish/replan loop;
  • calibrated uncertainty, evidence, provenance, and completion standards;
  • autonomy, initiative, disagreement, collaboration, and bounded recovery;
  • tool-family routing, while pi-agent tool schemas remain the source of exact arguments.

Roles specialize priorities and judgment but cannot override that contract. Current perceptions, focus, retrieved notes, skills, social context, and memory health remain in the dynamic continuation context. This keeps the stable prefix cacheable and prevents transient world content from acquiring system authority.

Every request an internal agent makes carries a fixed prefix — the system prompt (with the # COMMANDS roster, one copy) and the serialized tool schemas — plus the dynamic continuation prompt. The budget is enforced in code, not by convention:

  • The system prompt frame (everything but the role prose, roster included) has two budget tiers, chosen from the agent model’s context window (promptTierForContextWindow):

    Tier Models Frame cap Tools
    lean context window ≤ 32k tokens (small local models) LEAN_SYSTEM_PROMPT_BYTE_CAP 5,800 B minimal, unless the profile was set explicitly
    full larger windows, cached cloud models FULL_SYSTEM_PROMPT_BYTE_CAP 9,000 B the configured or role-inferred profile

    Both tiers render the same text today (worst case ≈ 5.2 KB in any trust profile × posture); the full cap is headroom for deliberate additions, and a role’s loop override is measured against its agent’s tier. test/prompt-budget.test.ts checks both caps in every trust profile × autonomy posture with the live roster.

  • Each command is introduced once. The # COMMANDS roster skips every command that TOOL ROUTING or MEMORY already names (taughtCommandNames), TOOL ROUTING points at marina_tool_search instead of repeating its catalog, and the memory tools’ descriptions defer to MEMORY for the verbs.

  • The full tool profile is resident core + deferred rest: the crew core set ships on every request together with one marina_tool_search whose description catalogs the remaining tools as name — one line; loading a tool by name makes it callable for the rest of the session. MARINA_DEFERRED_TOOLS=off restores the all-resident profile. marina_command is always resident.

  • marina_code (~4 KB) and think are on demand in every acting profile (ON_DEMAND_TOOL_NAMES): each profile’s marina_tool_search lists them. marina_code is resident while a coding task is bound (the Code Mode driver’s setActiveCodingTask loads it), for a coding role (CODE_TOOL_ROLES) and for an explicitly chosen profile.

  • Long trait and reflection procedures are built-in skills (skill builtin chronicling, canvas-intents, consolidate-memory); the trait or [Reflection Due] section keeps one line per rule and a pointer.

  • The typed analysis tools are deferred and listed by marina_tool_search: marina_forecast (forecast, typed answers, optional formation and retriever), marina_research (research ask: the web-research agent with a citation audit, or a research mode — evidence-loop, survey, authority — with a retriever), marina_swarm (web swarm), marina_quant / marina_calc, marina_data (markets, odds, series, polls, crowd), marina_decision_check, marina_triage, marina_arbiter and marina_pattern (pattern run). Each builds ONE world command (src/agent/analysis-commands.ts, shared with the tool policy) and runs it like marina_command, so the command’s rank, gates, rate limits, spend caps and audit apply unchanged. The crew and minimal profiles reach the same commands through marina_command.

  • The continuation prompt offers two budgeted, labelled hints about the agent’s focus: [Lessons] (every tenth cycle, ≤ 600 bytes; filtered to forecasting or research work when the focus or recent tools show it — lessons … for:<work>, MARINA_LESSONS_RESIDENT_DOMAIN) and [Skill] (every tenth cycle at offset 3, ≤ 700 bytes; the agent’s own best skill, else a relevant built-in — skill top, MARINA_SKILLS_RESIDENT).

  • marina_memory_service is the one resident memory-service tool (≤ 2 KB, assist_* operations included); the typed marina_memory_assistance variant is deferred.

  • The compactor (src/agent/context-manager.ts) counts tool schemas in the fixed prefix, anchors on provider-reported usage when the transcript carries it, and reserves the model’s output budget (MARINA_DEFAULT_MAX_TOKENS for the self-proxy; MARINA_LOCAL_OUTPUT_FRACTION, default 0.25, for local models) before budgeting the prompt.

  • The continuation prompt clamps each World Events line (400 chars; model_request payloads get MARINA_PERCEPTION_MODEL_REQUEST_MAX_CHARS), clamps the Active Coding Task, and fits sections to MARINA_CONTINUATION_BUDGET_BYTES (6000) by priority — World Events, the response mandate, and the action directive are never deferred; cadenced sections are deferred first, with a [+N sections deferred] note. Events that do not fit return to the buffer for the next cycle.

  • Prompt caching: the synthesized marina/* model emits Anthropic-style cache_control markers and a per-agent sessionId (MARINA_AGENT_PROMPT_CACHE=off disables the markers); the proxy is responsible for forwarding or stripping them per upstream.

  • Thinking budgets are configuration (AgentConfig.thinkingLevel: off | minimal | low | medium | high | xhigh). Resolution order: explicit config (agent spawn <name> thinking:high, agent config <name> thinking high) → crew responders off (their value is latency) → MARINA_AGENT_THINKING (default off). off neutralizes the model’s reasoning flags so no reasoning directive is sent at all. Any other level on the marina/* proxy marks the model reasoning-capable so pi-ai emits reasoning_effort: "<level>"; the proxy translates that per upstream — Anthropic gets thinking: {type:"enabled", budget_tokens} (1024 / 2048 / 8192 / 16384, xhigh clamps to high) with temperature/top_p omitted, OpenAI-compatible upstreams receive reasoning_effort verbatim. Registry models (anthropic/..., openai/...) take pi-ai’s native thinkingLevel / thinkingBudgets handling untouched. Runtime-only: not persisted to agent_configs.

  • Tool ordering: pi-agent-core executes a multi-tool turn in parallel by default. Every world-mutating tool (anything not in READ_ONLY_TOOL_NAMES — look, examine, who, brief, feed, web, think, code read/search/diff/history/…) is stamped executionMode: "sequential", so a batch containing one runs in assistant order while pure-read batches still fan out. MARINA_TOOL_EXECUTION=parallel drops the stamps; sequential serialises every batch at the Agent level. The one-channel-send-per-run beforeToolCall hook is a rate cap, not an ordering rule, and stays in force in every mode.

Room text, peer messages, notes, pools, web pages, files, model-request content, and tool results can all contain useful requests or evidence. They can also contain stale, mistaken, or adversarial instructions. The agent therefore treats them as data below the governing contract. A peer request may legitimately begin collaboration, but embedded text cannot redefine the agent’s role, disclose secrets, or cause unrelated actions.

This is an in-model defense, not a complete security boundary. Marina’s deterministic permissions, safety gates, scoped tools, and external policy enforcement remain authoritative. Current research continues to find that prompt-only defenses are insufficient against adaptive injection.

An active pi-agent turn must use a tool to affect the world; private prose is not delivered. That mechanical fact does not make every tool call progress. The contract requires a justified response, state change, retrieval, artifact, or handoff. think, repeated observation, routine notes, and unrelated movement cannot substitute for an actionable response. Silent-turn recovery uses the same rule, and repeated failures trigger a changed strategy or clean handoff instead of a loop.

Completion is evidence-based. A focus reaching its time horizon triggers review, never an automatic claim of completion. Compaction preserves objective, success criteria, verified evidence, decisions, commitments, plan state, failed approaches, contradictions, and the next action. Transcript content is summarized as untrusted historical evidence rather than silently promoted into policy.

The design follows several converging primary sources:

Prompt changes must pass structural tests for hierarchy, provider neutrality, prompt size, dynamic context labeling, plan-preserving compaction, and human-agent symmetry. They must also pass agent, context-manager, role, tool-profile, model-resolution, and autonomy regression suites. For behavioral A/B work, use the frozen smoke set — bun run eval-prompt, or in the world benchmark run smoke --model marina:answerer, which records the run on the smoke leaderboard; compare task success, required evidence, meaningful primitive use, total tokens, latency, calls, retries, and outcome quality. Fewer calls or tokens count as improvements only when the outcome still passes.

Use system-prompt [role <name>] [goal <text>] to inspect the assembled in-system prompt without changing it. MARINA_SYSTEM_TOOLS_PROSE=off remains an experimental A/B switch; tool schemas and the compact profiles continue to provide functional coverage when it is disabled.