Task Statement 2.2·Domain 2 — 18% of exam
Structured Error Responses
Implement structured error responses for MCP tools
Official Exam Guide Objectives
Task 2.2: Implement structured error responses for MCP tools.
Knowledge of
- The MCP isError flag pattern for communicating tool failures back to the agent
- The distinction between transient errors (timeouts, service unavailability), validation errors (invalid input), business errors (policy violations), and permission errors
- Why uniform error responses (generic "Operation failed") prevent the agent from making appropriate recovery decisions
- The difference between retryable and non-retryable errors, and how returning structured metadata prevents wasted retry attempts
Skills in
- Returning structured error metadata including errorCategory (transient/validation/permission), isRetryable boolean, and human-readable descriptions
- Including retriable: false flags and customer-friendly explanations for business rule violations so the agent can communicate appropriately
- Implementing local error recovery within subagents for transient failures, propagating to the coordinator only errors that cannot be resolved locally along with partial results and what was attempted
- Distinguishing between access failures (needing retry decisions) and valid empty results (representing successful queries with no matches)
What You Need to Know
What a failing MCP tool hands back determines whether the agent can do anything sensible about it. "Operation failed" tells a model nothing it can act on: not what broke, not whether another attempt would help, not what to try instead.
The protocol provides isError for exactly this. Setting it marks the response as a failure rather than a result, which is the difference between an agent reasoning about recovery and an agent treating the error text as the answer it asked for.
The Four Error Categories
Every tool failure falls into one of four categories. Each one calls for a different response, and telling them apart is only possible if the response says which it is.
1. Transient Errors Timeouts, service unavailability, rate limits. Nothing is wrong with the request; the system on the other end is briefly out of reach. Recovery: wait, then send the same call again.
{
"isError": true,
"content": [{
"type": "text",
"text": "Service temporarily unavailable"
}],
"errorCategory": "transient",
"isRetryable": true,
"description": "The order database is under load and refused the connection. Nothing is wrong with this request; sending it again shortly should work."
}2. Validation Errors Malformed input, absent required fields, values outside the permitted range. Here the request itself is at fault. Recovery: correct the input, then send it again.
{
"isError": true,
"content": [{
"type": "text",
"text": "Invalid order ID format"
}],
"errorCategory": "validation",
"isRetryable": true,
"description": "Order IDs take the form #NNNNN, for example #12345. This call supplied 'order-abc'. Reformat the identifier and send it again."
}3. Business Errors A policy violation, a limit exceeded, a rule that forbids what was asked. The call is well-formed and the system understood it perfectly — and refused. Recovery: do NOT retry, because the rule will apply identically next time. The agent needs a different route entirely.
{
"isError": true,
"content": [{
"type": "text",
"text": "Refund exceeds policy limit"
}],
"errorCategory": "business",
"isRetryable": false,
"description": "£750 is above the £500 ceiling for automatic refunds, so this one needs a manager to approve it. Hand the refund details to a human agent."
}isRetryable: false is doing the important work there. A policy does not relent on the second attempt, so anything short of a different path — escalation, usually — just burns calls arriving at the same refusal. Writing the description in terms a customer could hear also lets the agent explain the outcome rather than reporting an error code.
4. Permission Errors Access denied, credentials insufficient, authorisation refused. The obstacle is who is asking rather than what is being asked. Recovery: escalate, or come back with different credentials.
{
"isError": true,
"content": [{
"type": "text",
"text": "Access denied"
}],
"errorCategory": "permission",
"isRetryable": false,
"description": "Financial records are outside what this service account may read. Pass the request to a senior agent whose access covers the financial system."
}What isRetryable Really Signals
The flag answers one narrow question: could any retry ever succeed? It does not claim the identical call will work. Transient and validation errors both carry isRetryable: true and reach success by different routes — the transient one by resending unchanged once the service recovers, the validation one only after the agent repairs the input, turning order-abc into #12345. Business and permission errors share isRetryable: false for the complementary reason: a rule that blocks the request blocks it every time, and a credential problem is solved by a different principal rather than a different wording. So read isRetryable for whether to try again at all, and errorCategory for what trying again would have to involve — resend, self-correct, escalate, or route around.
Access Failure vs Valid Empty Result
Of everything in this domain, this is the distinction to nail. The exam tests it directly.
Access failure: the query never ran. Something timed out, authentication was refused, the service was unreachable. Whether the data exists is unknown, because nothing got far enough to look.
Valid empty result: the query ran and the answer is nothing. The system was reached, the search executed, and no record matched. Retrying repeats a successful operation to obtain the same correct answer.
Blur the two and recovery logic stops working. Here's how that plays out:
A tool returns an empty array after a customer lookup. The agent retries 3 times, then escalates to a human. Analysis reveals the customer's account simply does not exist.
Nothing malfunctioned. The lookup worked, found no such customer, and reported that accurately. What went wrong is that "reached the database, no match" and "never reached the database" arrived looking identical, so the agent applied its failure handling to a success — three wasted calls and a human pulled in to confirm an answer it already had.
So shape the responses to make the two unmistakable: an empty answer from a query that ran should share no surface with a query that never ran at all.
// Valid empty result — NOT an error
{
"isError": false,
"content": [{
"type": "text",
"text": "The search ran and matched nothing for 'john@example.com'. No such customer exists — this is an answer, not a failure."
}],
"resultCount": 0
}
// Access failure — IS an error
{
"isError": true,
"content": [{
"type": "text",
"text": "Could not reach customer database"
}],
"errorCategory": "transient",
"isRetryable": true,
"description": "The customer database did not answer within 5 seconds, so the search never ran. Whether a match exists is still unknown."
}Error Propagation in Multi-Agent Systems
Across several agents, the governing principle is that failures are handled as low down as possible and only travel upward when they cannot be:
- Subagents implement local recovery for transient failures. A search that times out is retried by the search subagent, without the coordinator ever learning it happened.
- Only propagate errors that cannot be resolved locally. Once local recovery is exhausted, the failure goes up — at that point it is genuinely the coordinator's decision.
- Include partial results and what was attempted. Bare failure is not enough to decide with: "I searched 3 of 5 sources successfully. Sources 4 and 5 timed out. Here are partial results from the 3 successful sources."
Two anti-patterns are ruled out by this. Swallowing an error and reporting an empty success hides the failure from the only component able to compensate for it. Aborting the entire workflow on one subagent's failure discards work that succeeded and was recoverable. Both leave the coordinator deciding without the information it needed.
Deep Dive
MCP's two error-reporting mechanisms
The MCP specification distinguishes two separate error channels, and mixing them up is a common source of bugs. Protocol errors are standard JSON-RPC errors for transport/routing problems: unknown tools, invalid arguments, server errors. Tool execution errors are reported inside a successful tool result with isError: true, covering API failures, invalid input data, and business logic errors. A tool that exists and was called correctly but then fails internally should return a normal JSON-RPC success envelope with isError: true in the payload — not a protocol-level error. This is the mechanical basis for the whole error-category taxonomy in this lesson: every one of the four categories (transient, validation, business, permission) is a tool execution error, never a protocol error.
Sourcemodelcontextprotocol.io › toolsfetched 2026-07-30
isError in MCP maps to is_error in the Messages API
The MCP spec's isError flag has a direct analogue in Anthropic's own Messages API: a client tool_result block carries an optional is_error boolean, set true when tool execution failed, and Claude "incorporate[s] this error into its response to the user." When Claude connects to a remote MCP server through the Messages API's MCP connector (rather than a client-side tool loop), results come back as mcp_tool_result content blocks that carry the same boolean, e.g. {"type": "mcp_tool_result", "is_error": false, "content": [...]}. Whichever path you're building against, the pattern is identical: a boolean flag inside the result, not an HTTP-style status code, tells the model whether to treat the payload as a success or a failure to reason about.
Sourcesplatform.claude.com › handle-tool-callsplatform.claude.com › mcp-connectorfetched 2026-07-30
structuredContent and outputSchema turn ad-hoc JSON into a contract
Rather than hand-rolling errorCategory/isRetryable/description inside a text string (as the Appendix A build steps do for simplicity), MCP has a first-class field for this: structuredContent, a JSON object returned alongside the result. For backwards compatibility, a tool that returns structured content should also serialise the same JSON into a TextContent block. If the tool declares an outputSchema, the contract tightens further: the server MUST provide structured results conforming to it, and the client SHOULD validate results against it. Declaring an outputSchema for your error payload is how you guarantee every failure response actually has errorCategory, isRetryable, and description — instead of trusting every code path to remember to include them.
Sourcemodelcontextprotocol.io › toolsfetched 2026-07-30
The spec says a human SHOULD be able to deny tool invocations
MCP's design guidance states there "SHOULD always be a human in the loop with the ability to deny tool invocations." This is the protocol-level justification for treating permission errors as a distinct, non-retryable category rather than something to route around automatically: the spec's whole trust model assumes a human can say no, so a tool that returns a permission error is reporting that the system said no, and the correct response is escalation, not a workaround.
Sourcemodelcontextprotocol.io › toolsfetched 2026-07-30
Claude's own malformed-call retries are a different mechanism from isRetryable
Don't conflate two different retry behaviours. If Claude's tool call itself is invalid or missing required parameters, Claude automatically "retries 2-3 times with corrections before apologizing to the user" — this happens at the model level, before your tool code even runs successfully. isRetryable in your structured error response is a different signal: it fires after your tool executed and failed, telling the agent whether attempting the same (or a corrected) request again could ever succeed. A validation error your tool returns (bad input format) is isRetryable: true because the agent can fix the input and resubmit — that's a deliberate, agent-driven retry, distinct from Claude's automatic malformed-call correction loop.
Sourceplatform.claude.com › handle-tool-callsfetched 2026-07-30
The Agent SDK converts uncaught handler exceptions to error results automatically
If you build your MCP tool with the Claude Agent SDK's custom-tools API, "a handler error doesn't stop the agent loop" — the SDK's in-process MCP server catches uncaught exceptions in your handler and converts them into error results for you. That's a safety net, not a substitute for the structured-error design in this lesson: an uncaught exception becomes a generic error, but explicitly returning isError: true with your own errorCategory/isRetryable/description payload is how you compose the specific message the agent actually needs to recover intelligently, rather than falling back on whatever the SDK's default exception serialisation produces.
Sourcecode.claude.com › custom-toolsfetched 2026-07-30
Quick Reference
| Fact | Value |
|---|---|
| MCP's two error mechanisms | Protocol errors (JSON-RPC: unknown tool, invalid args, server errors) vs tool execution errors (isError: true inside a successful result) |
isError semantics | true = tool execution failed; model reasons about recovery instead of treating text as a normal result |
| Messages API equivalent | tool_result.is_error (optional boolean); MCP connector mcp_tool_result.is_error |
structuredContent | JSON object field for structured tool output; also serialise to a text block for back-compat |
outputSchema | If declared: server MUST conform, client SHOULD validate — guarantees error fields are always present |
| Four error categories | transient (retry after delay) · validation (fix input, retry) · business (never retry, escalate) · permission (escalate / different credentials) |
isRetryable | Answers "can a retry ever succeed" — true for transient/validation, false for business/permission |
| Access failure vs valid empty result | Access failure = isError: true (couldn't reach data); empty result = isError: false, resultCount: 0 (reached data, found nothing) |
| MCP human-in-the-loop principle | Spec: there SHOULD always be a human able to deny tool invocations — the basis for treating permission errors as escalate-only |
| Claude's automatic malformed-call retry | 2-3 automatic retries with corrections for invalid/missing tool-call parameters — separate from your isRetryable metadata |
| SDK handler error handling | Uncaught exceptions auto-convert to error results; explicit isError: true lets you compose the specific recovery message |
| Multi-agent error propagation | Local recovery for transient failures; propagate only unresolvable errors, with partial results and what was attempted |
Exam Traps
Practice Scenario
A tool returns an empty array after a customer lookup. The agent retries 3 times, then escalates to a human agent. Analysis shows the customer's account simply does not exist. What is the root cause of this wasted effort?
Build Exercise
Build Structured Error Responses for All Four Categories
Difficulty: Intermediate (2/4)
45 minutes
- Create an MCP tool that queries a mock customer database with simulated failure modes
Why: Simulating failure modes in a controlled environment lets you observe how agents behave when errors lack structure. The exam tests your understanding of how poor error responses cause wasted retries and incorrect escalations.
You should see: An MCP server running with a customer_lookup tool that accepts a customer identifier and a failure_mode parameter to trigger specific error conditions on demand.
- Implement four error response types: transient (simulated timeout), validation (invalid input format), business (refund exceeds policy limit), and permission (access denied)
Why: Each error category demands a different recovery strategy. The exam tests whether you can identify which category an error belongs to and what recovery action is appropriate. Transient errors are retryable; business errors never are.
You should see: Four distinct error responses, each with isError: true, a specific errorCategory value, the correct isRetryable boolean, and a descriptive message explaining what went wrong and what to do next.
- Include structured metadata in each error: errorCategory, isRetryable boolean, and a human-readable description
Why: Structured metadata is what enables intelligent recovery. Without these fields, the agent cannot distinguish a transient timeout from a permanent policy violation. The exam specifically tests whether you know that isRetryable: false means the agent must take an alternative path, not retry.
You should see: Each error response parses to a JSON object containing exactly three fields: errorCategory (one of transient, validation, business, permission), isRetryable (boolean), and description (a sentence explaining the error and suggesting recovery).
- Implement a valid empty result response (isError: false, resultCount: 0) clearly distinguished from an access failure
Why: This is one of the most critical distinctions in Domain 2. Confusing access failures with valid empty results causes wasted retries and incorrect escalations. The exam tests this directly — an agent retrying a successful empty query is the canonical anti-pattern.
You should see: Two structurally different responses: a valid empty result with isError: false and resultCount: 0 (indicating the query ran successfully but found nothing), and an access failure with isError: true, errorCategory: transient, and isRetryable: true.
- Write an agent loop that reads the error metadata and takes appropriate action: retry for transient, fix input for validation, escalate for business, and request credentials for permission
Why: The agent loop demonstrates the practical outcome of structured error metadata. Each error category maps to a specific recovery action, and the loop must branch correctly. This is exactly the kind of decision logic the exam expects you to design.
You should see: An agent loop that parses the error metadata, branches on errorCategory, retries transient errors up to 3 times with backoff, reformats input for validation errors, escalates business errors to a human, and requests elevated credentials for permission errors.
Sources
- Claude Certified Architect Foundations Exam Guide — Domain 2, Task Statement 2.2 — Anthropic
- MCP Specification — Tool Results — Model Context Protocol
- Building Effective Agents — Anthropic — Anthropic
- MCP Specification — Tools (2025-06-18) — Model Context Protocol
- Handling tool calls — Anthropic API Documentation — Anthropic
- MCP connector — Anthropic API Documentation — Anthropic
- Agent SDK — Custom Tools — Anthropic
Appendix A — Build Exercise Step Hints
Progressive hints revealed by the "Stuck? Get a nudge" control on each step.
Step 1. Create an MCP tool that queries a mock customer database with simulated failure modes
Why: Simulating failure modes in a controlled environment lets you observe how agents behave when errors lack structure. The exam tests your understanding of how poor error responses cause wasted retries and incorrect escalations.
You should see: An MCP server running with a customer_lookup tool that accepts a customer identifier and a failure_mode parameter to trigger specific error conditions on demand.
Stuck? Get a nudge
Step 2. Implement four error response types: transient (simulated timeout), validation (invalid input format), business (refund exceeds policy limit), and permission (access denied)
Why: Each error category demands a different recovery strategy. The exam tests whether you can identify which category an error belongs to and what recovery action is appropriate. Transient errors are retryable; business errors never are.
You should see: Four distinct error responses, each with isError: true, a specific errorCategory value, the correct isRetryable boolean, and a descriptive message explaining what went wrong and what to do next.
Stuck? Get a nudge
Step 3. Include structured metadata in each error: errorCategory, isRetryable boolean, and a human-readable description
Why: Structured metadata is what enables intelligent recovery. Without these fields, the agent cannot distinguish a transient timeout from a permanent policy violation. The exam specifically tests whether you know that isRetryable: false means the agent must take an alternative path, not retry.
You should see: Each error response parses to a JSON object containing exactly three fields: errorCategory (one of transient, validation, business, permission), isRetryable (boolean), and description (a sentence explaining the error and suggesting recovery).
Stuck? Get a nudge
Step 4. Implement a valid empty result response (isError: false, resultCount: 0) clearly distinguished from an access failure
Why: This is one of the most critical distinctions in Domain 2. Confusing access failures with valid empty results causes wasted retries and incorrect escalations. The exam tests this directly — an agent retrying a successful empty query is the canonical anti-pattern.
You should see: Two structurally different responses: a valid empty result with isError: false and resultCount: 0 (indicating the query ran successfully but found nothing), and an access failure with isError: true, errorCategory: transient, and isRetryable: true.
Stuck? Get a nudge
Step 5. Write an agent loop that reads the error metadata and takes appropriate action: retry for transient, fix input for validation, escalate for business, and request credentials for permission
Why: The agent loop demonstrates the practical outcome of structured error metadata. Each error category maps to a specific recovery action, and the loop must branch correctly. This is exactly the kind of decision logic the exam expects you to design.
You should see: An agent loop that parses the error metadata, branches on errorCategory, retries transient errors up to 3 times with backoff, reformats input for validation errors, escalates business errors to a human, and requests elevated credentials for permission errors.
Stuck? Get a nudge
Appendix B — Interactive Study Prompts
Two prompts to paste into Claude. B1 drills the judgement the exam actually measures; B3 reviews the code you wrote for the Build Exercise above. The exam simulator between them is the interactive quiz on this page.
B1. Concept Check — Discrimination Drill
You are examining me for the Claude Certified Architect – Foundations (CCAR-F) exam, Domain 2: Tool Design & MCP Integration (18% of the exam), Task Statement 2.2: Structured Error Responses. Use British English throughout.
What this exam actually measures. Not one item on the official exam asks what something is. Every item drops you into a production system that is already misbehaving, offers four defensible engineering responses, and asks which is best. The skill being tested is proportionality: fix the root cause with the cheapest instrument that gives the guarantee the situation demands. So do not quiz me on definitions. Make me choose between options that are both defensible, then attack whatever I chose.
How to run this session.
- One question at a time. Stop and wait. Never answer your own question, and never move on until I have committed.
- Never reveal which option is right before I commit to one.
- Do not praise me. A correct answer earns "Yes" and the next question. If I am right for the wrong reason, say so — that is the failure that costs marks on exam day.
- When I am wrong, quote the exact phrase in my answer that gave it away, correct it in one sentence, and move on. One correction at a time.
- If I write something fluent but empty, name it: "That is a restatement, not a reason."
- Set every scenario inside one of the exam's production contexts: the Customer Support Resolution Agent (Agent SDK, MCP tools
get_customer,lookup_order,process_refund,escalate_to_human), the Multi-Agent Research System (a coordinator delegating to web-search, document-analysis, synthesis and report-generation subagents), or Developer Productivity with Claude (an agent over an unfamiliar codebase usingRead,Write,Bash,Grep,Glob).
Session plan — about twelve questions.
Round 1 — Anchor (1 question). One concrete question to check I have actually read the material. If I cannot answer it, stop the session and tell me to read the lesson before continuing.
Round 2 — Discrimination (5 questions). Each one: describe a symptom in one of the contexts above, with a number or a log observation in it. Offer exactly two responses, both defensible. Ask me to pick one and justify it in a single sentence. Then argue the case for the option I rejected as strongly as you can, and ask whether I am holding or changing my answer. Only after I answer that, tell me which is right and why the other one is the more tempting trap.
Round 3 — Proportionality (2 questions). Take one symptom and run it twice with different stakes: once where the cost of an error is a wasted retry, once where it is an incorrect refund or a corrupted production branch. The right answer must change between the two. If I answer the same way both times without noticing the stakes moved, that is the finding — tell me.
Round 4 — Code review (3 questions). Present a colleague's confident proposal containing one of the trap errors listed below, written the way a teammate would write it in a pull request. Ask me what is wrong with it. Do not signal that anything is wrong.
Round 5 — Verdict. Rate me green, amber or red on each concept below. Name the single weakness most likely to cost me marks, and give me one specific next action: a section of this lesson to re-read, or a step of the Build Exercise to redo. If I am not ready for this task statement, say so plainly.
Concepts in scope
- The MCP
isErrorflag — a tool that ran and failed reports it inside an otherwise successful result by settingisError: true, which tells the model the execution failed so it can reason about recovery rather than read the error text as a normal answer. - The four error categories — transient (timeout, service unavailable, rate limit), validation (bad format, missing field), business (policy violation, limit exceeded) and permission (access denied), each demanding a different recovery.
- Structured metadata — every failure carries an
errorCategory, anisRetryableboolean and a human-readable description with recovery guidance; strip those and the agent cannot tell a momentary outage from a permanent policy breach. - What
isRetryableactually claims — whether any retry can ever succeed, not that the same request will: a transient error resends unchanged, a validation error resends only after the agent repairs the input, and business and permission errors never resolve by retrying at all. - Access failure versus valid empty result — a query that could not run is an error the agent may retry; a query that ran and matched nothing is a success with a result count of zero, and retrying it just produces the same emptiness three times before a needless escalation.
- Error propagation across agents — subagents recover locally from transient failures and pass upward only what they cannot resolve, carrying partial results and an account of what was attempted, instead of suppressing the failure or tearing down the whole workflow.
Trap errors to plant in Round 4
- Retrying a lookup that returned an empty result from a query which ran perfectly well.
- Returning "Operation failed" with no category, no retryability flag and no description behind it.
- Marking a refund that breached the policy limit as retryable and letting the agent try it again.
- Having a subagent swallow its own failure and hand the coordinator an empty result dressed as a success.
Stay inside the material above. If I raise something outside it, tell me it is out of scope for this task statement and return to the drill. Begin with Round 1.
B2. Exam Simulator
Exam simulator
Question 1 of 10
Scenario · Customer Support Resolution Agent
Your support agent looks up a customer by email, receives an empty array, retries three times and escalates to a human. The ticket review shows the account simply never existed and the database was reachable throughout. Roughly 4% of conversations end this way. What change would most effectively prevent this wasted effort?
B3. Build Coach — Code Review
The Build Exercise and its hint ladder are already on this page. This prompt is for the one thing the page cannot do: review the code you actually wrote.
You are a staff engineer reviewing my implementation of a build exercise for the Claude Certified Architect – Foundations exam, Domain 2, Task Statement 2.2: Structured Error Responses. Use British English throughout.
I am building a customer lookup tool with structured failures and an agent that recovers from them: an MCP tool over a mock customer database that can be driven into each failure mode on demand, returning a distinct structured error for each of the four categories, separating a valid empty result from an access failure, and an agent loop that branches on the metadata — retrying transient failures with backoff, repairing and resubmitting on validation, escalating business rule violations to a human, and requesting different credentials on a permission failure.
It has to satisfy all of the following:
- The tool takes a customer identifier plus a parameter that selects which failure to simulate, so every scenario can be triggered on demand.
- Four distinct failure responses exist, each flagged as an error, each with its own category, the correct retryability value, and a description saying what went wrong and what to do next.
- Every failure payload parses to an object carrying exactly those three metadata fields, with the category drawn from the four permitted values.
- The empty result is structurally different from the access failure: one is a success carrying a result count of zero, the other is a flagged, retryable, transient error.
- The agent loop branches on the category — bounded backoff retries for transient, input repair for validation, escalation for business, a credentials request for permission — and does not retry the empty result at all.
How to review.
- Ask me to paste my code, including the tool handler and the agent-side recovery branch. If I have not pasted any, ask for it and nothing else. Do not write the implementation for me, do not offer a reference solution, and do not fill in a step I have skipped.
- Work through the criteria above in order. For each one, quote the line of my code that satisfies it, or say plainly that nothing does.
- Then hunt for the failure modes below. Each is a real production bug, not a style preference.
- Rank everything you find: (1) would fail in production, (2) would lose marks on the exam, (3) style. Give me the first item under (1) and then stop — wait for my fix before giving me the next one.
- If my code satisfies everything, do not congratulate me. Change the requirements — the same lookup now times out twice and then returns an empty result — and make me walk through exactly what the agent does at each of the three steps.
- If I ask you to just write it for me, refuse once and give me the smallest nudge that would unblock me instead.
Failure modes to probe
- The empty result routed through the same code path as the timeout, so the agent spends its whole retry budget and escalates over a customer who simply does not exist.
- A business error given a retryable flag, so the agent resubmits a refund that the policy will refuse every time instead of escalating it once.
- Retryability read as "resend the identical request", so validation errors go back unchanged rather than being reformatted first.
- A failure reported as a protocol-level error rather than as a successful result carrying the error flag, so the model never sees the metadata and cannot reason about recovery.
- A code path that omits one of the three fields — usually the description — leaving the agent's branch to fall through to a generic retry, or letting an uncaught exception carry the failure so the model gets a default serialisation instead of the message you composed.
Start by asking me for my code.