Capstone and Retrospective: Turning a Team's Conventions Into a Skill Pack and Driving a Subagent Through a Real Task
Combine the week's learning into one delivery: split a team's conventions document into three skills, use subagent isolation to run a real task, use an eval to prove it's actually better than going without skills, and write it up as one portfolio entry.
Today's Goals
- Split a team's conventions document into three skills with clear, non-overlapping boundaries
- Design a set of eval cases that prove the difference in output with and without skills
- Write up this delivery as a portfolio entry that holds up under follow-up questions
The last day teaches no new concepts and instead combines six days into one complete delivery: take a real team conventions document, split it into three skills, hand a real job to a clean subagent, and use a set of assertions to prove it genuinely helps — not that it feels better, but by how many percentage points the pass rate rose. Then compress the delivery into one portfolio entry that survives follow-up questions. Once you have read the walkthrough and finished the lab, scroll back to the top and tick off the three goals.
Plain-Language Walkthrough
What you deliver is capability, not documents
Pin down the acceptance criteria first, or the last day easily becomes "wrote a few more files."
This delivery's product is not those three SKILL.md files but one conclusion that survives questioning: on a given set of tasks, the pass rate went from this to that with this package, measured under these conditions. The three SKILL.md files are only intermediate artifacts toward that conclusion.
The standard follows from that: can somebody who was not involved reproduce that number from your delivery document? If they cannot, however beautifully the files are written, the delivery is not finished.
One last use of the filing cabinet metaphor: for six days you built the cabinet, the index cards, and the distribution. What today proves is that the cabinet genuinely made new hires make fewer mistakes — not that everybody says it is handy, but that with the same batch of tasks run before and after, you counted the errors.
From a conventions document to three skills: split by trigger situation, not by chapter
Given a team conventions document, the most natural move is to split along its table of contents: chapter one one skill, chapter two another. That is the most common mistake.
Chapter structure serves a human's reading order, usually running from concept to detail; a skill's boundary must serve the trigger situation, because the model decides whether to open it at the moment a user has just said something. Those two structures almost never coincide.
Splitting by trigger situation takes three steps in practice.
Step one, read the document once and note only when somebody would need this passage. Note situations, not content. A thirty-page engineering handbook usually compresses to a dozen situations.
Step two, cluster the situations by "the same moment." The format of a commit message, the allowed type values, and what the body should say may be scattered across three chapters, but all three are used at the single moment of "I am about to commit" — they are one skill. Conversely, "how to write a commit message" and "how to split a commit," discussed in the same chapter, are two moments and must be separated.
Step three, write one description per cluster and check for mutual exclusion. Use day three's positive-and-negative apparatus here: write three sentences that would trigger each skill and two similar-looking ones that should not, then run them and see whether they steal from each other. Stealing means the clustering was not clean, so go back to step two.
There is one further class of content to handle separately: the deterministic rules in the document — the type may only be one of these six, the version number must match this pattern. Those are better distilled into a validation script per day four's criteria, leaving the skill's body one line saying to run the validation script when finished.
Driving a subagent: why isolate a clean session
The three skills are installed, so how do you try them? Not in the session you have been debugging in for two hours.
That session's context is already scattered with the convention fragments you typed by hand, the wording you corrected, the examples you pasted. The model performs well under those conditions and you conclude the skill did it — when in fact you recited the answer yourself in the session. That is the most common self-deception in evaluating a skill.
The right approach hands it to a subagent: an executor with its own separate context window that starts from a clean slate, carries only what you specify, and hands the result back when done.
It brings three things, each serving today's acceptance directly.
First, the context is clean. A subagent does not inherit the main session's conversation history. Whatever you said or corrected in the main session, it knows nothing of. Only results from that setup genuinely reflect the skill's effect.
Second, capabilities can be bounded precisely. A subagent's definition can declare which tools it may use and which model, and can declare which skills to preload — which is especially useful for a controlled comparison: the with-skill arm states them explicitly and the without arm leaves it empty, with every other condition identical.
Third, noise stays out of the main session. It keeps the file digging, the trial and error, and the script runs in its own context and hands back only the conclusion.
A subagent definition is a Markdown file with frontmatter in a conventional directory:
---
name: convention-runner
description: Complete commit, review, and release tasks per the team conventions
tools: Read, Grep, Bash
model: sonnet
skills:
- team-conventions:commit-message
---
You are an executor working strictly to the team conventions. Do only the one thing asked,
and change no other files. Before handing back the result, self-check it against the
conventions line by line.In a controlled experiment the two definitions differ only by that skills line. Any other difference — a different model, a different tool set, one extra sentence of prompt — makes your conclusion unable to say whose credit it was.
Evals: how to write assertions
With a clean execution environment, the next step is today's most technical: turning better into a number.
An eval case has three parts: one prompt, a description of the expected output, and two to four judgeable assertions. The assertions are the whole point; write them badly and the eval is just sighing in a new location.
Judgeable means: not whether the output is good, but whether a fact holds. A comparison makes it clear:
- Not judgeable: "the commit message is clearly written," "the review comment is valuable" — still feelings.
- Judgeable: "the type field is one of those six values," "the scope field equals a directory that genuinely exists in the repository," "the body does not repeat the list of file names already in the diff," "the first line is at most 50 characters."
An assertion is best checking one thing only. Three assertions each checking one thing are far more useful than one checking three, because on failure you immediately know which one broke.
How should an eval set be balanced? Positive, boundary, and negative at roughly five to three to two. Positives are the most common usage; boundaries are inputs that nearly should trigger a different skill; negatives are inputs that definitely should not trigger, with the assertion written as "this skill was not activated." Without negatives you cannot detect an over-broad trigger surface — and over-broad is a skill's most common failure.
Running it is plain: the same set of cases, run once by the with-skill subagent and once by the without, judged case by case, with a pass rate for each side.
type Assertion = { id: string; describe: string; check: (output: string) => boolean }
type Case = { id: string; prompt: string; kind: 'positive' | 'boundary' | 'negative'; assertions: Assertion[] }
type Run = { caseId: string; output: string }
export type Report = { total: number; passed: number; rate: number; failures: string[] }
/** A case passes only when every assertion holds. Record failures individually, since the detail is what guides edits. */
export function score(cases: Case[], runs: Run[]): Report {
const byCase = new Map(runs.map((r) => [r.caseId, r.output]))
const failures: string[] = []
let passed = 0
for (const c of cases) {
const output = byCase.get(c.id)
if (output === undefined) {
failures.push(`${c.id}: no run record for this case`)
continue
}
const failed = c.assertions.filter((a) => !a.check(output))
if (failed.length === 0) passed += 1
else failures.push(...failed.map((a) => `${c.id} / ${a.id}: ${a.describe}`))
}
return { total: cases.length, passed, rate: passed / cases.length, failures }
}
/** The comparison's conclusion is one number: the difference in pass rate. Both arms must run the same cases. */
export function compare(withSkill: Report, without: Report): string {
const delta = (withSkill.rate - without.rate) * 100
return `without ${(without.rate * 100).toFixed(0)}% -> with ${(withSkill.rate * 100).toFixed(0)}%, up ${delta.toFixed(0)} percentage points`
}from dataclasses import dataclass
from typing import Callable
@dataclass
class Assertion:
id: str
describe: str
check: Callable[[str], bool]
@dataclass
class Case:
id: str
prompt: str
kind: str # positive | boundary | negative
assertions: list[Assertion]
@dataclass
class Report:
total: int
passed: int
rate: float
failures: list[str]
def score(cases: list[Case], runs: dict[str, str]) -> Report:
"""A case passes only when every assertion holds. Failure detail is what guides edits."""
failures: list[str] = []
passed = 0
for case in cases:
output = runs.get(case.id)
if output is None:
failures.append(f"{case.id}: no run record for this case")
continue
failed = [a for a in case.assertions if not a.check(output)]
if not failed:
passed += 1
else:
failures.extend(f"{case.id} / {a.id}: {a.describe}" for a in failed)
total = len(cases)
return Report(total, passed, passed / total if total else 0.0, failures)
def compare(with_skill: Report, without: Report) -> str:
"""The comparison's conclusion is one number: the difference in pass rate."""
delta = (with_skill.rate - without.rate) * 100
return f"without {without.rate:.0%} -> with {with_skill.rate:.0%}, up {delta:.0f} percentage points"Writing it up as a portfolio entry
This delivery deserves a place on your resume, but only if written correctly. An entry that survives questioning has three things.
A number, and the conditions it was measured under. "Improved code convention consistency with skills" is empty; "across 20 review tasks, convention compliance rose from 55% to 90%, with the same model, the same prompt, and two subagent arms differing only in whether the skills were preloaded" is questionable in the good sense. Giving the final value without the starting point is giving nothing.
What you gave up. That is the one part of the entry nobody can copy, and where the follow-up questions concentrate. For example: "the three skills total just over three hundred lines, with all the background and history from a thirty-page handbook left out — the criterion being whether the model would get it wrong without a line," or "deterministic format validation did not go into the body but was distilled into a script."
Why not the alternative. An interviewer will certainly ask why these rules were not simply written into the system prompt. The answer came on day one, and today you should be able to give it in one breath: the system prompt is resent every turn, so twenty conventions are billed continuously; and dearer still is attention, where a system prompt stuffed with unrelated rules lets rule seventeen interfere while working on the third thing. A skill's value is not how much it holds but that it stays closed until needed.
The seven-day retrospective and what to learn next
Look back at the through-line of these seven days: from one folder to one conclusion that survives questioning. Day one established what a skill is, day two wrote the first one that triggers, day three turned authoring into method, day four added scripts, day five saw from the runtime's side how it gets loaded, day six made it handable to others, and today proved it genuinely helps.
If you take away only three sentences:
First, the description is the only trigger surface. It is the one stretch of text in this mechanism that you pay for every turn and the one that decides success or failure.
Second, capability gaps are filled by tools and experience gaps by skills. Get that cut wrong and every later selection decision is wrong.
Third, determinism goes to code and judgment stays with the model. It explains at once when to write a script and when to write the body.
Two roads from here, both sister courses released in the same batch, and which to take depends on what you lack.
Missing the wiring, go learn MCP. You can now hand experience to a model, but the model still has none of your company's tools and data in hand. MCP in 7 Days: wiring tools into any agent runs from the protocol triangle to remote deployment and security governance, and day six's prompt injection and least privilege is a lesson you cannot skip when this package actually rolls out across a team.
Missing the trade-offs, go learn context engineering. Skills helped you close away what should not be resident, but the context still has the system prompt, tool results, retrieved passages, and history messages competing for room. Context Engineering in 5 Days covers exactly how that bill is computed, how long sessions are compacted, and how failure modes are triaged — and day five's token bill and utilization metrics can be taken straight over to add another dimension to today's eval.
Source Reading
Hands-On Lab
The easiest one to fudge today is criterion 3. The moment the two arms have a second difference, your number cannot say whose credit it was — a swapped model, an extra tool, half a sentence of changed prompt, all count. Before starting, put the two subagent definitions side by side and diff them, confirming only that one line differs.
- Read the solution's delivery document and see by what trigger situations its three skills were split.
- Fill in the conventions document's split table in the starter, writing each skill's boundary and what it does not handle.
- Fill in the eval case table, writing each case's prompt, expected output, and two to four judgeable assertions.
- Record the results of running with and without skills, judge case by case, and compute the pass rate difference.
- Compress the whole delivery into one portfolio entry, noting the measurement conditions of every number.
Interview Questions
Today's 3 questions are in the question bank below, weighted toward splitting and accepting a skill pack, eval design and baseline comparison, and presenting results. Expand each one and read the analysis before the key points — practicing the derivation beats memorizing bullets. The high-frequency labels for the domestic and overseas markets are there so you can pick by target market.
Checklist and Tomorrow
- Split a team's conventions document into three skills with clear, non-overlapping boundaries
- Design a set of eval cases that prove the difference in output with and without skills
- Write up this delivery as a portfolio entry that holds up under follow-up questions
- Explain why a controlled experiment needs a clean subagent rather than a session you have been debugging in
- All 5 acceptance criteria of the lab pass
- Answer at least 2 of the 3 interview questions without looking at the key points
The seven days end here. Look back at day one's "a skill is a folder containing a SKILL.md" and you should now hear how much it left out — how to write a description that triggers accurately, how many layers the body takes, when a script belongs, how a runtime loads it, how a set of skills is handed to a team, and how to prove it genuinely helps. The format really is simple; writing experience down clearly never was. Next, go fill in the half you lack: missing the wiring, take MCP in 7 Days; missing the trade-offs, take Context Engineering in 5 Days.
Interview questions
How do you prove a skill actually helps rather than just feeling better?你怎么证明一个 skill 真的有用,而不是感觉上更好?
Common in ChinaCommon overseasDeep dive#agent-skills#evaluation#methodologyHow to reason about it · think before answering
- This tests evaluation skill and honesty. Saying it felt better ends the answer; the interviewer wants a reproducible comparison.
- Give the structure first: one set of cases, two arms differing in exactly one variable, per-assertion judging, and a pass-rate comparison. The conclusion is a single number, the delta.
- Then explain how to keep the comparison clean, the half most people skip. Never test in the session you spent two hours debugging: that context is littered with convention snippets you typed and corrections you made, so good output reflects you, not the skill. Use a fresh subagent, with the two definitions differing only in which skills are preloaded.
- Describe the case mix: positive, boundary and negative roughly five to three to two. Negatives are non-negotiable because they measure whether the trigger surface is too wide, which is the most common way a skill goes wrong. Without them, a skill that grabs everything scores perfectly.
- Assertions are the core. Decidable means checking facts, not quality: the type field is one of six values, the scope equals a real directory in the repository, the first line is under fifty characters. Written clearly is not decidable. One assertion checks one thing so failures point somewhere.
- Close on honesty: some judgments resist reliable assertions, such as whether a review comment found the real problem. Forcing an assertion yields false green. Mark those as human-judged, sample a few, and say so in the conclusion.
- Expected follow-up: does a small sample support the claim? Be candid. A small sample supports a claim about that batch of tasks only, so every number carries its measurement conditions and is never extrapolated into a general efficiency gain.
分析过程 · 先想清楚再作答
- 这题在考评估能力,也在考诚实。答「我试了几次感觉好多了」直接出局,面试官要的是一个可复现的对照。
- 先给整体结构:同一批用例、两组只差一个变量、逐条判定、比通过率。**结论只有一个数:通过率差值。**
- 然后讲对照怎么做干净,这是本题最容易被忽略的一半。**绝对不要在你调试了两小时的那个会话里试**——那个上下文里散落着你手打的规范片段和你纠正过的措辞,模型产出得好是因为你自己把答案说了一遍。要用一个上下文干净的子代理,两份定义只差「预加载哪几个 skill」这一行,模型、工具集、提示词全部一致。
- 再讲用例集怎么配:正例、边界例、负例大约五比三比二。负例不能省,它测的是触发面有没有过宽,而**过宽是 skill 最常见的坏法**——少了负例,一个什么都抢的 skill 也能拿满分。
- 断言是全部重点。可判定的意思是不看好坏、只看事实成不成立:「类型字段取自那六个值之一」「范围等于仓库里真实存在的目录名」「首行不超过 50 个字符」是可判定的;「写得清楚」不是。一条断言只查一件事,失败时才知道是哪一条挂了。
- 最后补诚实这一层:有些判断写不出可靠断言,比如「这条评审意见有没有抓住真问题」。硬凑只会得到假绿,老实标成人工判定、抽查几条、并在结论里注明有几条是人工判的。**一份诚实的部分自动化评估远好过一份全绿的假评估。**
- 可预期的追问是「样本量这么小,结论站得住吗」。答话要坦率:小样本只能支撑「在这一批任务上」的结论,所以每个数字都要带测量条件,不要外推成通用效率提升。
Key points
- Same cases, two arms differing in one variable, judged per assertion, compared by pass rate.
- The comparison needs a context-clean subagent, never the session you debugged in.
- The two subagent definitions differ only in preloaded skills; model, tools and prompt are identical.
- Include negative cases: they measure an over-wide trigger surface, the most common failure.
- Assertions must be decidable and single-purpose; mark human-judged cases honestly in the conclusion.
答题要点
- 同一批用例、两组只差一个变量、逐条判定、比通过率差值。
- 对照必须用上下文干净的子代理,不能在调试过的会话里试。
- 两份子代理定义只差预加载 skill 那一行,模型、工具、提示词全部一致。
- 用例要含负例,它测触发面有没有过宽,过宽是最常见的坏法。
- 断言要可判定、一条只查一件事;判不了的老实标人工判定并在结论里注明。
How many skills should a thirty-page team convention document become, and how do you split it?一份三十页的团队规范文档要拆成几个 skill,按什么切?
Common in ChinaCommon overseasIntermediate#agent-skills#design#decompositionHow to reason about it · think before answering
- It sounds open-ended but has a clear wrong answer. Splitting by chapter is almost always wrong, and explaining why is where the points are.
- Chapter structure serves a human reading order, usually concept then detail. A skill boundary must serve the trigger moment, because the model decides whether to open it right after the user speaks. The two structures rarely coincide.
- Give three steps. First, read the document recording only when someone would need each passage. Record situations, not content; thirty pages usually yields a dozen situations.
- Second, cluster situations by shared moment. Commit message format, allowed types and body content may sit in three chapters but all apply at the moment of committing, so they are one skill. Writing a commit message and splitting commits share a chapter but are two moments, so they split.
- Third, write one description per cluster and test mutual exclusivity with three triggering phrases and two near-miss non-triggers each. If they compete, the clustering is not clean; go back to step two.
- Raise something interviewers probe: most of the document belongs in no skill. Background and history matter to people and are pure overhead for a model. The test remains whether omitting a line would make the model get it wrong. Thirty pages compressing to a few hundred lines is normal.
- Add the special case: deterministic rules such as an allowed type set or a version format belong in a validation script, leaving the body to say run the validator.
- Expected follow-up: how many exactly? The count follows the clustering. Seven or eight that still compete usually means the situations were recorded too finely; exactly one means you were still thinking about the document as a whole.
分析过程 · 先想清楚再作答
- 这题看着开放,其实有明确的对错。答「按章节切」几乎必错,能说清为什么错才是拿分点。
- 先给错的那条:**章节结构是为人的阅读顺序服务的**,通常从概念讲到细节;而 skill 的边界必须为触发场景服务——模型是在「用户刚说了一句话」这个时刻决定要不要翻开它。这两种结构几乎从不重合。
- 然后给正确的三步。第一步通读文档,只记「什么时候有人会用到这一段」,记场景不记内容,三十页通常能压出十来个场景。
- 第二步把场景按**同一个时刻**聚类。提交信息的格式、类型的取值、正文写什么,可能分散在三章里,但都在「我要提交了」这一刻被用到,它们是一个 skill;同一章里的「怎么写提交信息」和「怎么拆提交」是两个时刻,要拆开。
- 第三步为每个聚类写一句描述并检查互斥:各写三句会触发的话、两句形似但不该触发的话,跑一遍看有没有互相抢。**抢了说明聚类没聚干净,回第二步。**
- 还要主动说一件面试官爱追问的事:**文档里有一大半内容不该进任何 skill**。背景、沿革、当初为什么这么定,对人有价值,对模型是纯负担。判据仍是「不写这条,模型会不会做错」。三十页压成三四百行是正常的。
- 最后补一类特殊内容:确定性的规则(类型只能是这六个、版本号必须匹配某个格式)更适合沉淀成校验脚本,正文只留一句「写完跑一次校验」。
- 可预期的追问是「到底该切几个」。答案是数量由聚类结果决定而不是先定,但如果切出七八个还互相抢,通常是场景记得太细了;如果只切出一个,说明你还是按文档整体在想。
Key points
- Do not split by chapter: chapters serve reading order, skill boundaries serve trigger moments.
- Three steps: record situations, cluster by shared moment, write descriptions and test with positive and negative examples.
- Competing descriptions mean bad clustering; go back rather than patching the wording.
- Most of the document enters no skill; the test is whether omitting it would cause a mistake.
- Deterministic rules become a validation script, leaving one line in the body.
答题要点
- 不能按章节切,章节服务人的阅读顺序,skill 边界服务触发时刻。
- 三步:只记使用场景、按同一个时刻聚类、写描述并用正负例查互斥。
- 互相抢说明聚类没聚干净,要退回重聚,不是改描述糊过去。
- 文档里一大半内容不进任何 skill,判据是不写这条模型会不会做错。
- 确定性规则沉淀成校验脚本,正文只留一句跑校验。
What is the difference between running a task in a subagent with skills and running it in the main session?让子代理带着 skill 去执行任务,和在主会话里执行有什么区别?
Common in ChinaCommon overseasDeep dive#agent-skills#subagent#evaluationHow to reason about it · think before answering
- This tests the value of context isolation. A shallow answer reduces it to opening a new session. Name three effects and the problem each solves.
- First, a clean context. A subagent does not inherit the main conversation, so it knows nothing you said or corrected. This is decisive for evaluation: testing a skill in a session you debugged for two hours usually measures your own hints, the most common self-deception here.
- Second, precisely bounded capability. A subagent definition can declare its tools, its model, and which skills to preload. For a controlled comparison the two definitions differ only in that line, because any second difference makes the result unattributable.
- Third, noise stays out. File reading, trial and error and script runs live in the subagent's own context, and only the conclusion comes back, leaving the main window for the thread that must stay coherent.
- Name the costs too. Without the main context, the handoff prompt must be explicit, and a vague task description sends a subagent off course faster than the main session. It also pays for its own system prompt and skill catalog.
- An implementation detail shows real experience: skills reach a subagent either by preloading in the definition, which injects the full body at startup, or by letting it discover and activate them during execution. Use preloading for controlled comparisons and discovery for real work.
- Expected follow-up: when should you not use one? When the task needs back-and-forth with the user or depends heavily on dozens of earlier turns. There, isolation is the defect rather than the feature.
分析过程 · 先想清楚再作答
- 这题考的是上下文隔离的价值,答得浅会变成「子代理就是开个新会话」。要说清它带来的三件事,以及每一件对应什么问题。
- 第一件是**上下文干净**。子代理不继承主会话的对话历史,你说过什么、纠正过什么它一概不知道。这一条在做评估时是决定性的:在调试了两小时的会话里试 skill,模型产出得好往往是因为你自己在会话里把答案说了一遍,这是评估 skill 时最常见的自欺。
- 第二件是**能力可以精确限定**。子代理定义里能声明可用工具、模型,也能直接声明预加载哪几个 skill。做对照时两份定义只差这一行,其它完全一致——任何第二个差异都会让结论说不清是谁的功劳。
- 第三件是**噪音不进主会话**。翻文件、试错、跑脚本这些过程留在子代理自己的上下文里,只把结论交回来。主会话的窗口因此能留给真正要连贯推进的那条线。
- 还要说清代价,只说好处会显得没做过。子代理拿不到主会话的上下文,意味着**交接摘要要写清楚**,任务描述含糊时它比主会话更容易跑偏;而且它多跑一遍系统提示与技能目录,不是免费的。
- 补一个实现细节能显出实感:skill 进子代理有两条路,一是在定义里预加载、启动时就注入完整正文,二是让它在执行中自己发现并激活。做对照实验用预加载,因为它把变量固定住了;做真实任务用自动发现,更接近日常。
- 可预期的追问是「什么时候不该用子代理」。答案是任务需要跟用户来回确认、或强依赖前面几十轮的上下文时——隔离带来的干净,这时候正好是缺陷。
Key points
- A subagent has its own context window and no inherited history, which is what makes a clean comparison possible.
- Its definition bounds tools, model and preloaded skills, so a controlled pair differs in one line.
- Process noise stays inside the subagent; only the conclusion returns.
- The costs are an explicit handoff prompt, more drift on vague tasks, and paying for another system prompt.
- Preload for controlled experiments, discovery for real work, and skip isolation when the task needs user back-and-forth.
答题要点
- 子代理有独立上下文窗口,不继承主会话历史,这是做干净对照的前提。
- 定义里能限定工具、模型与预加载的 skill,对照时两份定义只差那一行。
- 过程噪音留在子代理里,只把结论交回主会话。
- 代价是交接摘要必须写清楚,任务含糊时更容易跑偏,且多付一次系统提示的开销。
- 预加载适合做对照实验,自动发现更接近真实使用;需要与用户反复确认的任务不适合隔离。