Skip to content

How to shape agent behavior with a system prompt

A system prompt tells the model who it is and how it should behave — before any task arrives. In Murmur, the system prompt is injected as the system parameter on every inference call, not just the first turn, so the agent's persona and constraints are reinforced throughout a multi-turn session. This guide covers the two ways to set a system prompt and when to choose each.

The relevant manifest options are:

Option Controls
inference.system_prompt Inline text injected as the system prompt on every turn
inference.system_prompt_file Path to a file whose content is used as the system prompt
inference.system_prompt_artifact Name of a skill artifact whose skill.md is read at launch and used as the system prompt

Step 1 — add an inline system prompt

Create a murmur.yaml file with inference.system_prompt set to the text you want the model to receive:

name: my-agent
version: "0.1.0"

artifacts:
  - name: murmur-driver-anthropic
    version: "1.0.0"
    runtime: driver

inference:
  transport: http
  endpoint: https://api.anthropic.com
  model: claude-sonnet-5
  api_key: ${ANTHROPIC_API_KEY}
  driver:
    artifact: murmur-driver-anthropic
  system_prompt: |
    You are a concise data analyst. Always respond with:
    1. A one-sentence summary of what you found.
    2. A bullet list of key numbers.
    Never include preamble or closing remarks.
name: my-agent
version: "0.1.0"

artifacts:
  - name: murmur-driver-openai
    version: "1.0.0"
    runtime: driver

inference:
  transport: http
  endpoint: https://api.openai.com
  model: o3-mini-high
  api_key: ${OPENAI_API_KEY}
  driver:
    artifact: murmur-driver-openai
  system_prompt: |
    You are a concise data analyst. Always respond with:
    1. A one-sentence summary of what you found.
    2. A bullet list of key numbers.
    Never include preamble or closing remarks.
name: my-agent
version: "0.1.0"

artifacts:
  - name: murmur-driver-deepseek
    version: "1.0.0"
    runtime: driver

inference:
  transport: http
  endpoint: https://api.deepseek.com
  model: deepseek-r1
  api_key: ${DEEPSEEK_API_KEY}
  driver:
    artifact: murmur-driver-deepseek
  system_prompt: |
    You are a concise data analyst. Always respond with:
    1. A one-sentence summary of what you found.
    2. A bullet list of key numbers.
    Never include preamble or closing remarks.

The | block scalar preserves newlines. The runtime passes this text verbatim as the system field on every POST to the inference driver — including turn 2, turn 3, and beyond.


Step 2 — install dependencies

mur install
Different ways to install artifacts

mur install needs to know where to fetch artifacts from. You have two options:

Option A — configure a registry source in ~/.murmur/config.yaml:

registry:
  default: official
  sources:
    - name: official
      type: github
      repo: <owner>/<repo>
      token: "${GITHUB_TOKEN}"

Then install by artifact name and version:

mur install <artifact-name@version>

Option B — pass a full GitHub reference and skip configuration entirely:

mur install github:<username>/<repo>@<tag>

See Installing artifacts to learn more.


Step 3 — load the prompt from a file

For longer prompts, or when you want to version the prompt independently from the manifest, use system_prompt_file:

inference:
  ...
  system_prompt_file: conventions.md

The path is relative to the directory containing murmur.yaml, not to the session workdir. A typical layout:

my-capsule/
  murmur.yaml
  conventions.md        ← system prompt lives here
  murmur.lock

The runtime reads the file once at launch, before any inference call. If the file is missing or unreadable, mur run exits with error[E-RUN-009] before the session starts — you will never silently run a session with the wrong prompt.

conventions.md:

You are a strict code reviewer operating in a CI pipeline.

Rules:
- Only flag issues that violate the project's style guide.
- Output one finding per line in the format: `FILE:LINE — REASON`.
- If there are no issues, output exactly: `LGTM`.
- Do not explain, justify, or suggest alternatives.

Step 4 — load the prompt from a skill artifact

If your system prompt is already packaged as a skill artifact, you can bind it directly instead of duplicating the content in a separate file. Set inference.system_prompt_artifact to the name of the skill:

artifacts:
  - name: code-review-conventions
    version: "1.0.0"
    runtime: skill

inference:
  ...
  system_prompt_artifact: code-review-conventions

At launch, the runtime reads workdir/tools/code-review-conventions/skill.md and uses that content as the system prompt for every inference turn. The skill is not added to the callable tool inventory — it is already in context and would double-inject if called.

MURMUR.md notes the binding so the agent is aware:

## Installed Skills

- **code-review-conventions** — Project PR review conventions *(bound as system prompt — already in context, not separately callable)*

Validation happens at parse time:

  • The named artifact must be declared in artifacts: — if not, mur run exits with a clear error before starting.
  • It must declare prompt_payload: trueruntime: skill defaults to this, so skills work with no extra declaration; a tool, driver, or hook artifact must set prompt_payload: true explicitly to be eligible, and one that doesn't is a manifest error. See inference.system_prompt_artifact.
  • The skill's skill.md must be readable at launch — a missing file exits with error[E-RUN-009].

Step 5 — choose between inline, file, and artifact

Use system_prompt (inline) Use system_prompt_file Use system_prompt_artifact
Short prompts (< 10 lines) Long or structured prompts Persona already packaged as a skill
Single-file manifests Prompts version-controlled separately Capsules that want to distribute both the skill and the persona together
Prototyping and quick experiments Personas shared across multiple manifests Reuse the same skill content both as a persona and (in other capsules) as a callable

All three options are mutually exclusive — setting more than one in the same manifest is a parse error (error[E-MAN-003]).


Step 6 — verify the system prompt is applied

Create a task.md file with a question designed to reveal the persona:

Who are you and what are your rules?

Run the capsule:

mur run
murmur: url localhost:52222
session: ses_019ed2af53da75c2aefee84ee10c34af

After the session completes, read the agent's output:

cat workdir/<session_id>/out/result.txt

Replace <session_id> with the value printed by mur run. For the data analyst persona above, you would expect exactly one summary sentence and a bullet list — no preamble, no closing remarks.

The session trace records which prompt was in effect. Every session_start line in workdir/<session_id>/trace.jsonl carries system_prompt_source ("manifest", "cli" or "none") and system_prompt_sha256, the hash of the prompt as resolved:

mur trace show
Different ways to identify a session

mur trace show with no argument reads the most recent session:

mur trace show

To name another one, pass an ordinal counting back from the newest (@2), the last 4 or more characters of its ID (3e4b), the full ID, or a path to its trace.jsonl:

mur trace show @2
mur trace show 3e4b
mur trace show ses_6801f81dd28b4a9daf434e8324c4793e
mur trace show path/to/trace.jsonl

Use --workdir <path> if your session directories are not under ./workdir. Every command that names a session takes the same addresses — see Session addresses.

Other trace exploration commands

mur trace has four subcommands for exploring session output:

mur trace show — print the full trace for a session to the terminal.

mur trace steps — show a turn-by-turn summary of what the agent did in a session. Pass --verbose to include a truncated summary of each tool's input.

mur trace diff — compare the traces of two sessions side by side, or with no arguments the two most recent. Useful for spotting behavioural regressions between runs.

mur trace report — generate a structured summary report from a session's trace. Covers token usage, tool calls, latency, and other session-level metrics.

The prompt text is recorded only when you ask for it

system_prompt_source and system_prompt_sha256 are always written, and the hash alone tells you whether two sessions ran with the same prompt. To read the prompt itself, set trace.capture: content in the manifest and cat <session_id>/blobs/<system_prompt_sha256>. See Session trace schema.

If the agent is ignoring your constraints, add a more explicit rule to the system prompt and re-run.


Step 7 — use system_prompt_file for a shared persona

When multiple capsules need the same base persona, factor it into a shared file:

personas/
  analyst.md
  reviewer.md
capsule-a/
  murmur.yaml          → system_prompt_file: ../personas/analyst.md
capsule-b/
  murmur.yaml          → system_prompt_file: ../personas/analyst.md

Both manifests reference the same file. Updating the persona in one place updates all capsules that share it. The path is resolved relative to each manifest's directory, so a relative .. path works as long as the directory layout is consistent.


Step 8 — override the prompt for a single run

To try a different persona without editing murmur.yaml, pass mur run --system-prompt:

mur run --task task.md --system-prompt "You are a terse code reviewer. Reply with numbered findings only."
murmur: url localhost:52222
session: ses_019ed2af53da75c2aefee84ee10c34af
status:  ok

The flag replaces whichever of the three manifest fields the capsule declared — inline, file, or artifact — and applies just as well to a manifest that declared none. It never writes to murmur.yaml: the next run without the flag is back to the manifest's own prompt.

Two consequences worth knowing:

  • The value is trimmed. An empty or whitespace-only value clears the prompt entirely, so the run sends no system parameter beyond the runtime's own identity block — useful for checking how much of the agent's behaviour the persona is responsible for.
  • Overriding a system_prompt_artifact releases that skill back into the callable tool inventory, since it is no longer already in context. MURMUR.md lists it as callable for that run.

The trace records the override: session_start.system_prompt_source reads "cli", and system_prompt_sha256 is the hash of the trimmed value you passed.

On a capsule with no inference: block there is no prompt to override, and the run fails with error[E-IO-003] before anything is staged.


Summary

Setting Behaviour
inference.system_prompt: \| Inline text; injected verbatim on every inference turn
inference.system_prompt_file: path.md File content; read once at launch; path is relative to manifest directory
inference.system_prompt_artifact: name Skill artifact's skill.md read at launch and used as system prompt; skill not separately callable
More than one field set simultaneously Parse error error[E-MAN-003]
File or skill.md missing or unreadable Launch error error[E-RUN-009] — session never starts
No field set No system parameter is sent; model receives no system prompt
mur run --system-prompt "text" Replaces whichever field the manifest set, for that run only; value is trimmed; empty value clears the prompt; murmur.yaml untouched
mur run --system-prompt on a manifest with no inference: CLI error error[E-IO-003] — nothing is staged
session_start.system_prompt_source in trace.jsonl "manifest" | "cli" | "none", alongside system_prompt_sha256; the prompt text itself at blobs/<system_prompt_sha256> only under trace.capture: content