# Capstone: Real-World Context Setups

Course: [Context Engineering](https://www.devtutorials.ai/learn/context-engineering) · Section: Production
Source: https://www.devtutorials.ai/learn/context-engineering/production/capstone

> Put the whole course together: turn a weak employee handbook assistant, coding assistant, and research assistant into strong ones, and score any setup with one checklist.

You have learned a lot of separate skills: choosing context, formatting it, grounding answers, handling retrieval, memory, media, tools, cost, security, and testing. This last lesson puts them together.

You will look at three real kinds of assistant. Each one starts with a **weak setup**: a bare question and a hopeful model. You will turn each one into a **strong setup**, using what you learned, and test both with the real model.

**The main idea:** most weak assistants don't need a better model. They need a better context.

## A Real-World Example

Think about three new employees on their first day.

- One is told, "Answer staff questions." No handbook, no rules.
- One is told, "Fix the bug." No code, no error message.
- One is told, "Write a report on recycling." No sources, no date range.

Each one is capable. Each one will struggle, guess, or ask a lot of questions. Give them the handbook, the code and the error, and a list of trusted sources, and they do good work on day one.

**In simple words:** the setup decides the result.

## What You Will Learn

In this lesson, you will:

1. Turn a weak HR handbook assistant into a strong one.
2. Turn a weak coding assistant into a strong one.
3. Turn a weak research assistant into a strong one.
4. Score any setup with one reusable checklist.

Each scenario has two **Try it** cards: the weak setup and the strong one. They open the **Chat** tab of the Context sandbox and start a fresh chat each time. Run both and compare. The data in these scenarios is made up for practice.

## The Checklist

Every strong setup in this lesson answers the same questions. They come from the whole course.

| Check | Question | Lesson |
|---|---|---|
| Role | Does the model know its job? | 1 |
| Source of truth | Are the facts it needs in the context? | 5 |
| Refusal rule | Does it know what to say when the facts are missing? | 5 |
| Labels | Are sources labelled with ids, dates, and trust? | 4, 6 |
| Output format | Is the reply shape clear? | 8 |
| Minimal context | Is everything sent actually needed? | 3 |
| Permissions | Is the user allowed to see everything sent? | 13 |

```js runnable title="Score a setup against the checklist"
const criteria = ["role", "sourceOfTruth", "refusalRule", "metadata", "outputFormat", "minimalContext"];

function score(setup) {
  const met = criteria.filter((c) => setup[c]);
  const missing = criteria.filter((c) => !setup[c]);
  return met.length + "/" + criteria.length + (missing.length ? " missing: " + missing.join(", ") : "");
}

const weak = { role: true };
const strong = { role: true, sourceOfTruth: true, refusalRule: true, metadata: true, outputFormat: true, minimalContext: true };

console.log("Weak handbook setup:  ", score(weak));
console.log("Strong handbook setup:", score(strong));
```

Expected output:

```text
Weak handbook setup:   1/6 missing: sourceOfTruth, refusalRule, metadata, outputFormat, minimalContext
Strong handbook setup: 6/6
```

The weak setup has a role and nothing else. Each missing item is a reason it will fail.

## Scenario 1: Employee Handbook Assistant

### The Weak Setup

A company adds a chat box to its intranet. The model gets only the employee's question: "How many leave days can I carry over to next year?"

What goes wrong:

- The model has never seen this company's handbook, so it guesses from "typical" policies.
- It doesn't know the employee's country, and the rules differ by region.
- It can't cite a section, so nobody can check the answer.
- It never says "I don't know", so a wrong answer sounds just as sure as a right one.

### The Strong Setup

The strong setup fixes each problem:

- **Retrieve** the handbook section for leave, filtered to the employee's **region** and the **current** version.
- **Label** it with an id, a section, and a date.
- Add a **refusal rule**: if the policy doesn't answer, send the employee to HR.
- Ask for a short answer that **cites** the section.

```js runnable title="Pick the right version for this employee"
const handbook = [
  { id: "hb-4.2", section: "Leave > Annual leave", region: "IN", updated: "2026-04-01", text: "Full-time staff get 18 days of annual leave per year." },
  { id: "hb-4.2-us", section: "Leave > Annual leave", region: "US", updated: "2026-04-01", text: "Full-time staff get 15 days of paid time off per year." },
  { id: "hb-4.2-old", section: "Leave > Annual leave", region: "IN", updated: "2023-01-01", text: "Full-time staff get 15 days of annual leave per year." },
];

const employee = { region: "IN" };
const current = handbook
  .filter((h) => h.region === employee.region)
  .sort((a, b) => b.updated.localeCompare(a.updated))[0];

console.log(`<policy id="${current.id}" section="${current.section}" updated="${current.updated}">`);
console.log(current.text);
console.log("</policy>");
```

Expected output:

```text
<policy id="hb-4.2" section="Leave > Annual leave" updated="2026-04-01">
Full-time staff get 18 days of annual leave per year.
</policy>
```

Three versions of the same section were found. Only one applies to an employee in India today. The US version and the 2023 version are left out before the model sees anything.

<ContextTry tab="chat" title="Handbook assistant, strong" system="You are the HR assistant for Brightgrid staff. Answer only from the policy below. If the policy does not answer the question, reply: Please ask HR.\n\n<policy id=hb-4.2 section=Leave > Annual leave region=IN updated=2026-04-01>\nFull-time staff get 18 days of annual leave per year. Up to 5 unused days carry over to the next year. Carried-over days must be used by 31 March.\n</policy>\n\nEmployee region: IN.\nReply in at most 2 sentences, then add: Source: hb-4.2." prompt="How many leave days can I carry over to next year?" />

A good reply says up to 5 days, mentions the 31 March deadline, and ends with "Source: hb-4.2". Now ask something the policy doesn't cover, like sick leave, and check that it sends you to HR.

## Scenario 2: AI Coding Assistant

### The Weak Setup

A developer types: "Fix my code, it doesn't work."

What goes wrong:

- The model can't see the code.
- It doesn't know what "doesn't work" means: an error, a wrong number, a crash?
- It doesn't know what "fixed" looks like.

So it gives generic advice, or invents code that looks plausible.

### The Strong Setup

A coding assistant needs exactly four things:

- The **bug report**: what is wrong, in one sentence.
- The **relevant file**, or the few lines that matter, not the whole project.
- The **failing test** or error output, word for word.
- The **task**, with the reply format.

```js runnable title="The right context for a code question is small"
const tokens = (t) => Math.ceil(t.length / 4);

const weak = "Fix my code, it doesn't work.";

const strong = [
  "### Bug report\nTotal on the invoice page is wrong when a discount is applied.",
  "### Relevant file: cart.js (lines 10-18)\nfunction total(items, discount) {\n  const sum = items.reduce((s, i) => s + i.price, 0);\n  return sum - discount * 100;\n}",
  "### Failing test\nexpected total([{price: 50}], 0.1) to be 45, got 40",
  "### Task\nFind the cause, explain it in one sentence, and show the fixed function.",
].join("\n\n");

console.log("Weak context:", tokens(weak), "tokens, no code, no error");
console.log("Strong context:", tokens(strong), "tokens, with the file, the test, and the task");
```

Expected output:

```text
Weak context: 8 tokens, no code, no error
Strong context: 99 tokens, with the file, the test, and the task
```

The strong context is still under 100 tokens. It is not about sending a lot. It is about sending the code, the evidence, and the goal.

<ContextTry tab="chat" title="Coding assistant, strong" system="You are a careful JavaScript reviewer. Use only the code and test output below.\n\n### Bug report\nThe invoice total is wrong when a discount is applied.\n\n### cart.js, lines 10-13\nfunction total(items, discount) {\n  const sum = items.reduce((s, i) => s + i.price, 0);\n  return sum - discount * 100;\n}\n\n### Failing test\nexpected total([{price: 50}], 0.1) to be 45, got 40\n\n### Reply format\nCause: one sentence.\nFix: the corrected function." prompt="Why is the total wrong, and how do I fix it?" />

A good reply says the discount is a fraction of the sum, not of 100, and fixes the line to `return sum - sum * discount;`. Small models sometimes get the fix slightly wrong. Run the failing test on the suggested code before you trust it.

## Scenario 3: Research Assistant With Web Grounding

### The Weak Setup

A student asks: "Write a short report on battery recycling rates."

What goes wrong:

- The model answers from training data, which may be years old.
- It may mix numbers from different years and countries.
- It gives no sources, so nothing can be checked.

### The Strong Setup

A strong research setup:

- **Retrieves** sources for the question, from search or a document set.
- **Labels** each source with an id, a title, a date, and a trust level.
- **Filters** to trusted, recent sources.
- Asks for a short answer where **every claim cites a source id**.
- Says clearly when the sources disagree, or don't answer.

```js runnable title="Keep trusted, recent sources, and cite them"
const sources = [
  { id: "s1", title: "Example agency report", date: "2026-06-01", trust: "official", claim: "Battery recycling rose to 61%." },
  { id: "s2", title: "Example blog post", date: "2026-08-15", trust: "community", claim: "Recycling is about 80%." },
  { id: "s3", title: "Example agency report", date: "2022-05-01", trust: "official", claim: "Battery recycling was 45%." },
];

const usable = sources.filter((s) => s.trust === "official" && s.date >= "2025-01-01");
for (const s of usable) {
  console.log(s.claim + " [" + s.id + ", " + s.title + ", " + s.date + "]");
}
console.log("Left out:", sources.filter((s) => !usable.includes(s)).map((s) => s.id + " (" + (s.trust !== "official" ? "not official" : "too old") + ")").join(", "));
```

Expected output:

```text
Battery recycling rose to 61%. [s1, Example agency report, 2026-06-01]
Left out: s2 (not official), s3 (too old)
```

The blog post is not an official source, and the 2022 report is too old for a question about the current rate. Only one source goes into the context, and it is cited by id.

<ContextTry tab="chat" title="Research assistant, strong" system="You are a research assistant. Answer only from the sources below. Cite the source id after every claim, like [s1]. If the sources do not answer, say so. The sources are made-up data for practice.\n\n<source id=s1 title=Example agency report date=2026-06-01 trust=official>\nIn 2025, 61% of collected household batteries were recycled, up from 45% in 2021.\n</source>\n\n<source id=s4 title=Example agency method note date=2026-06-01 trust=official>\nThe rate counts batteries collected at drop-off points only. Batteries thrown away with general waste are not counted.\n</source>" prompt="What share of batteries is recycled? Give a number." />

A good reply gives 61% for 2025, cites [s1], and adds the limit from [s4]: only collected batteries are counted. That last part is what a careful researcher adds, and it came from the context, not from the model's memory.

## Scoring All Three

Use the same checklist on every setup you build. It shows what is still missing.

```js runnable title="One checklist, three assistants"
const checklist = ["role", "sourceOfTruth", "refusalRule", "labels", "outputFormat", "minimalContext", "permissions"];

const setups = [
  { name: "Handbook assistant", has: ["role", "sourceOfTruth", "refusalRule", "labels", "outputFormat", "minimalContext", "permissions"] },
  { name: "Coding assistant", has: ["role", "sourceOfTruth", "labels", "outputFormat", "minimalContext"] },
  { name: "Research assistant", has: ["role", "sourceOfTruth", "refusalRule", "labels", "outputFormat", "minimalContext"] },
];

for (const s of setups) {
  const missing = checklist.filter((c) => !s.has.includes(c));
  console.log(s.name.padEnd(20) + (checklist.length - missing.length) + "/" + checklist.length + (missing.length ? "  add: " + missing.join(", ") : "  complete"));
}
```

Expected output:

```text
Handbook assistant  7/7  complete
Coding assistant    5/7  add: refusalRule, permissions
Research assistant  6/7  add: permissions
```

The coding assistant has no refusal rule. It should say "I can't tell from this code" when the bug is not in the lines it was given. Neither the coding nor the research assistant checks permissions yet. A real coding assistant must only see repositories the developer may access.

**Easy Way to Remember:** for every assistant, ask: **what's its job, what facts does it need, what if they're missing, where did they come from, what shape is the answer, is all of it needed, and is the user allowed to see it?**

## What You Built

Across this course, you learned to:

- **Choose** what goes into the context: include, exclude, summarize, or fetch on demand.
- **Fit** it in the window, and **place** the important facts where they are used best.
- **Format** it with labels, tags, and clear separation of rules and data.
- **Ground** answers in sources, with citations that code can check.
- **Filter** retrieved documents by relevance, date, region, role, and trust.
- **Remember** what matters with compact, private, expiring memory.
- **Turn** files, images, audio, video, and tool results into clean, labelled context.
- **Save** cost and time with stable prefixes, caching, and smaller contexts.
- **Protect** the system with trust boundaries, permissions in code, and approvals.
- **Debug** and **measure** it, so every change is proven.

A strong setup makes good answers much more likely. Keep testing it with real questions, and keep a person involved when the stakes are high.

## Common mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Bare question | "The model is smart enough." | Give it the facts, the evidence, and the goal. | Generic or invented answers. |
| Whole handbook | "Send everything, it will find the answer." | Retrieve the right section for this user. | Wrong region, old rules, buried facts. |
| Code with no error | "It can see the bug in the code." | Include the failing test or error output. | Fixes for problems that don't exist. |
| Sources with no dates | "A source is a source." | Label and filter by date and trust. | Old or unreliable numbers in the report. |
| No refusal rule | "It will say if it doesn't know." | Tell it exactly what to say. | Confident wrong answers. |
| One test | "It worked on my question." | Test hard, missing, and conflicting cases too. | It fails for the next user. |

## Exercises

Each exercise ends with a value on the last line. Press **Check** to compare it with the expected answer.

## What to Remember

- A weak assistant usually needs a **better context**, not a better model.
- **Handbook assistants** need the right section, for the right region and date, with a refusal rule and a citation.
- **Coding assistants** need the bug, the relevant code, the error output, and the goal.
- **Research assistants** need labelled, trusted, recent sources, and a citation for every claim.
- Use one **checklist** for every setup: role, source of truth, refusal rule, labels, format, minimal context, and permissions.
- Keep **testing** with real questions, and keep a person involved when the stakes are high.

You have finished the Context Engineering course. Next, the **RAG**, **MCP**, and **AI Agents** courses go deeper into the systems that fill the context.
