Chapter 24 Exercises
These exercises build your fluency with PMCP agents and teams. Each one targets a specific tier from the chapter, ordered from mechanical setup (Tier 1) through the source-agnostic loop (Tier 2) to composition across four reference servers (Tier 3). Every exercise runs offline — no model provider, no API key, no network.
Exercise 1: Scaffold and Run an Agent from the CLI (Tier 1)
Difficulty: Introductory (10 min)
Practice the mechanical steps of getting an agent running without writing any Rust. The goal is to produce a scaffolded agent package on disk and drive its decision loop to a terminal outcome using the offline completion source.
Steps:
- Install the CLI if you have not already:
cargo install cargo-pmcp. - Scaffold a package into a fresh, empty directory:
cargo pmcp agent new research-agent. (The command refuses a non-empty destination unless you pass--force, and refuses a symlinked destination outright — that is a policy, not a bug.) cd research-agentand list what was emitted. Openagent.package.jsonand find the four things that define this agent: its instructions, itsllmslot, itsmax_tokens, and itsmax_iterations. Confirm that none of those four values appears insrc/main.rs.- Run the pin tripwire once to establish a green baseline:
cargo test --test pin. - Drive the loop offline:
cargo pmcp agent dev --source fixed.
Verify your solution
The exercise passes when BOTH of these hold. First, the scaffolded directory
contains agent.package.json, Cargo.toml, src/main.rs and tests/pin.rs
— four files, with the agent's identity in the JSON manifest and not in the
Rust. Second, the --source fixed run terminates and its final line names the
source and a terminal outcome of Completed:
✓ agent run (fixed) finished: Completed
If the run instead reports LimitReached, the loop is executing but hitting
the iteration or token cap in the manifest before it finishes — raise
max_iterations and re-run. If the command errors out mentioning an endpoint,
you left --source at its default (openai-compat) and it tried to reach a
local Ollama that is not running; add --source fixed.
Questions to answer:
- Run
cargo pmcp agent dev --source fixedfrom an empty directory outside the scaffold. It still runs. Where did the package come from, and why is that fallback deliberate rather than a bug? - The manifest carries an
llmslot rather than a literal model name. What fills that slot at startup, and what does that let you do when moving the same package from a laptop to a deployment?
Exercise 2: One Loop, Two Completion Sources (Tier 2)
Difficulty: Intermediate (25 min)
Observe the source-agnostic loop invariant directly. The goal is to watch one
AgentEngine, driven by one ResolvedAgentConfig, complete a run against two
structurally different completion sources — a local scripted mock and a real
pmcp::Client answering sampling requests — and to confirm that both halves
ran, not merely that the example exited.
Steps:
- Build the example explicitly, naming its crate:
cargo build -p pmcp-agent --example s50_standalone_vs_sampled. The-pis load-bearing — thes50number is also taken in the rootexamples/directory. - Run it and capture the whole transcript, not just the tail:
cargo run -p pmcp-agent --example s50_standalone_vs_sampled | tee s50.txt. - In
s50.txt, locate the two labelled section headers. The first names the mock source; the second names the hosted adapter and the sampling source. - Open
crates/pmcp-agent/examples/s50_standalone_vs_sampled.rsand find the two functions behind those sections. Compare how each obtains its completion source, then compare how each invokes the loop. Write down, in one sentence, what differs and what does not. - Run the repository's own assertion of the same claim:
cargo test --test docs04_examples_run. Note which of its three legs corresponds to this exercise.
Verify your solution
The exercise passes when the captured transcript contains ALL THREE of the following — the two section headers AND the closing banner:
== 1. STANDALONE (mock CompletionSource) ==
== 2. HOSTED-SAMPLED (AgentServer + SamplingSource) ==
Done — the same AgentEngine ran standalone and hosted-sampled.
Checking the banner alone is not sufficient, and that is the entire point of
this exercise. The banner is a claim that both styles ran; the two section
headers are the evidence. A transcript carrying the banner but only one
section header would be asserting something it did not earn — so verify the
evidence, then the claim. (tests/docs04_examples_run.rs asserts the same
closing banner programmatically, which is why the string above is exact rather
than paraphrased.)
If the example does not run at all and complains that a binary is missing, you
skipped step 1: cargo test does not build example targets, so the
example must be built before any test or command can run it.
Questions to answer:
- The hosted half builds its completion source through a
CompletionSourceFactoryrather than receiving aCompletionSourcedirectly. What information is unavailable at construction time that forces that deferral? - In the hosted half the agent is called as a tool and issues
sampling/createMessagerequests. Which of those makes it a server, which makes it a client, and why is holding both roles the normal condition rather than an edge case?
Exercise 3: Run a Whole Team Across Four Reference Servers (Tier 3)
Difficulty: Advanced (40 min)
Bring it together. The goal is to run a complete doc-review flow in a single offline process — two member agents, one human role, and all four reference servers — from both the CLI and the example, and to trace one step of the flow back to the server that owns it.
Steps:
- Run the built-in fixture from the CLI:
cargo pmcp team dev. Read the numbered transcript it prints and note how many steps it walks. - Build the example, which is feature-gated:
cargo build -p pmcp-team-servers --example doc_review_team --features runtime. Confirm for yourself that omitting--features runtimemakes Cargo refuse to build the target rather than building a degraded one. - Run the example and record its exit status:
cargo run -p pmcp-team-servers --example doc_review_team --features runtime; echo "rc=$?". - In the output, find the human-in-the-loop step. Identify which reference server owns it, and find the two separate operations that ask for sign-off and record the verdict.
- Find the final dispatch step and the
_metakey it surfaces. Confirm the key is the spec-levelio.modelcontextprotocol/related-taskrather than a PMCP-private name.
Verify your solution
The exercise passes when the example's output contains the completion string
doc-review flow complete AND the process exits with status 0:
✅ doc-review flow complete — 4 hosting task(s) torn down cleanly.
All four reference servers cooperated in ONE offline process.
rc=0
Both halves are required. The completion string alone would tell you the flow
reached its end but not that teardown succeeded; a zero exit alone would tell
you the process did not crash but not that the flow ran. doc-review flow complete is the exact string tests/docs04_examples_run.rs asserts for this
example — the count of torn-down hosting tasks after the dash is free to
change as the reference set evolves, so match on the phrase, not the number.
If the build fails with a message about a missing required feature, you
dropped --features runtime from step 2. If the example builds but the run
hangs, you are almost certainly looking at a different example — this one
binds no sockets and needs no network, so it should complete in well under a
second.
Questions to answer:
- Asking for approval and recording the verdict are two distinct tool calls rather than one blocking call. What does that model correctly about a human participant that a single blocking call would model wrongly?
- The entire run is deterministic and offline because an injected
FixedSourceFactoryoverride replaces any live LLM. Why does that make the example testable, and what would be lost if the demo required a real model key?
Prerequisites
Before starting these exercises, ensure you have:
- Completed Chapter 24 (Agents & Teams), including the source-agnostic loop invariant discussion.
- A working Rust development environment and the PMCP repository checked out, so the examples cited above resolve to real paths.
cargo-pmcpinstalled (cargo install cargo-pmcp) for Exercises 1 and 3.- Examples built before they are run.
cargo testdoes not build example targets, so a test or command that executes an example will report a missing binary until you build it explicitly with thecargo buildinvocation named in each exercise. This trips people up exactly once.
No API key, model provider, or network access is required. Every exercise here runs against an offline completion source by design.
Next Steps
After completing these exercises, continue to:
- Chapter 23 Exercises -- Skills hands-on practice; the Skills chapter's dual-surface invariant is the closest structural sibling to this chapter's source-agnostic loop invariant.
- Chapter 21 Exercises -- Task lifecycle and polling, the mechanism the hosted-sampled run in Exercise 2 polls to a terminal state.
- Appendix A: cargo pmcp Reference -- The complete CLI surface behind Exercises 1 and 3.