# Output Format and Examples

Course: [Agent Skills](https://www.devtutorials.ai/learn/agent-skills) · Section: Skill Authoring
Source: https://www.devtutorials.ai/learn/agent-skills/authoring/output-contracts

> Defining the exact shape of a skill's reply: fixed headings, field formats, allowed values, None for empty sections, JSON for programs, one good example line, and templates with blanks to fill.

An **output format** is the fixed shape of a skill's reply. In this lesson, you will learn to write one. You will also learn to show it with one example, and to start big files from a template.

Without a fixed shape, every reply looks different.

For example:

- One reply says "Severity: high".
- Another says "**HIGH**".
- Another has no findings section at all.

People cannot find things quickly.

Scripts cannot read the reply at all.

**Simple lesson:** tell the skill exactly what the reply must look like.

### A Real-World Example

A delivery form has the same boxes every time.

- Name.
- Street.
- City.
- Postcode.

Because every form is the same, a machine can sort millions of letters.

A skill's output format works the same way. Every reply has the same headings, in the same order.

Click the button and open the **Contract check** tab.

- **Reply without the skill:** it misses all four headings.
- **Reply with the skill:** switch to **Use the last Run output** after a Run. Every heading is found.

**Simple lesson:** a fixed shape makes a reply easy to check.

## What You Will Learn

In this lesson, you will learn:

1. **Output format:** the headings every reply must have.
2. **Field format:** how one line must look.
3. **Allowed values:** the only words a field may use.
4. **Empty sections:** why you write "None".
5. **JSON:** when a program reads the reply.
6. **Examples:** one good line that shows the shape.
7. **Templates:** files with blanks the agent fills in.

**About this lesson's Skill Lab**

- Every DevKit skill has a `## Output format` section.
- The lab reads the headings from that section.
- The **Contract** badges show which headings a reply has.

## Fixed Headings

**Output format** = the list of headings every reply must have.

You write it in `SKILL.md`, under `## Output format`:

```markdown
## Output format
- ## Findings
- ## OWASP mapping
- ## Fixes
- ## Residual risk
```

Each heading must appear in the reply.

They must use the same words every time.

They must come in the same order every time.

Watch the lab check two real replies against these headings:

The reply with the skill has every heading. The one without has none.

Here are the headings some DevKit skills use:

| Skill | Headings in its reply |
| --- | --- |
| `ui-review` | Accessibility · Design system · UX · Fixes |
| `react-component` | Component · Test · Usage |
| `api-endpoint` | Route · Request and response · Errors · Implementation · Tests |
| `security-review` | Findings · OWASP mapping · Fixes · Residual risk |
| `test-planner` | Happy path · Edge cases · Error paths |

**Important:**

- Do not change the words. "Bug fixes" one week and "Fixes" the next breaks scripts.
- Put the headings in reading order. Findings come before fixes.

**Simple lesson:** fixed headings tell readers and scripts where to look.

## Field Formats and Allowed Values

Headings say **where** things go.

A **field format** says **how one line must look**.

Example:

```text
- [High] api/user.js:41 - query joins user input into SQL. Use a parameterized query.
  ^severity ^file:line     ^problem                           ^fix
```

Every finding has the same four parts.

So a reader can scan the list fast.

And a script can check every line.

**Allowed values** = the only words a field may use.

For example:

- **Severity:** Critical, High, Medium or Low.
- **PR verdict:** Approve, Approve with comments or Request changes.
- **Test layer:** unit or integration.

A word like "Urgent" is not on the list. So a check can reject it.

**Simple lesson:** list the allowed values, so wrong words are easy to catch.

## Empty Sections

Sometimes a section has nothing in it.

For example, there are no breaking changes.

If the skill drops the heading, scripts break. Readers wonder if it was forgotten.

So always write "None" under an empty heading.

```markdown
## Breaking changes
None
```

"None" is useful news. People want to know there are no breaking changes.

**Simple lesson:** never drop a heading. Write "None" instead.

## When a Program Reads the Reply

Most replies are read by people. Headings work best for them.

Some replies are read by a program first.

For example:

- A dashboard that counts findings.
- A CI step that fails the build.
- A tool that creates tickets.

For these, ask for **JSON**:

```markdown
## Output format
Return only a JSON array. Each item:
{ "severity": "Critical|High|Medium|Low", "file": "path", "line": 12, "fix": "text" }
```

Do not force JSON on people. It is hard to read.

- **People read it:** use headings.
- **A program reads it:** use JSON.
- **Both read it:** give a short summary with headings, then the JSON.

**Simple lesson:** choose the format for the first reader.

Click the button and open the **Library** tab.

- **Add one line** under `## Output format`: "Each finding: `- [Critical|High|Medium|Low] file:line - problem. Fix.`"
- **Press Save**, then run the **Security review** sample in the Run tab.
- **Look closely:** the recorded reply writes `line 1:`, not `file:line`. Your new rule would catch it.

**Simple lesson:** a clear field format shows mistakes early.

## Show One Good Example

Rules alone still leave room for guesses.

One example shows the exact shape.

**Example** = a real input and the exact line you want back.

```markdown
## Examples
`- [unit] parsePrice("") throws InvalidPrice`
```

This one line shows three things:

- The layer tag, `[unit]`.
- The call, `parsePrice("")`.
- The result, `throws InvalidPrice`.

Watch how one example line shapes a whole test plan:

Every case in the skill's reply copies the example's shape.

You can also add a **bad example**, clearly labelled:

```markdown
Good: `- [High] api/user.js:41 - query joins user input into SQL. Use a parameterized query.`
Bad (no location, no fix): `- SQL injection somewhere.`
```

Models copy examples very closely.

- Check every example follows your own rules.
- Avoid odd file names. Replies may repeat them.
- Keep one short example in `SKILL.md`.
- Put long examples in `examples/`, and name them in a workflow step.

Click the button and open the **Run** tab.

- **Without the skill:** one vague sentence.
- **With the skill:** every case has a layer tag, a call and a result.

**Simple lesson:** one good example often works better than many rules.

## Start From a Template

Some replies are whole files. For example, a React component and its test.

**Template** = a file with blanks the agent fills in.

Templates live in the skill's `templates/` folder.

A workflow step says when to use them:

```markdown
## Workflow
1. Start from templates/Component.tsx and templates/Component.test.tsx.
```

Blanks look like `{{Name}}`.

The agent must fill every one.

Watch the agent fill the component template:

A leftover `{{...}}` is easy to miss by eye. A simple check finds it every time.

Click the button and open the **Library** tab.

- **Look at** `templates/Component.tsx` and `templates/Component.test.tsx`.
- **Find** every `{{...}}` blank.

Good template ideas:

| Template | Used by |
| --- | --- |
| `Component.tsx`, `Component.test.tsx` | `react-component` |
| `endpoint.ts`, `endpoint.test.ts` | `api-endpoint` |
| `pull-request.md` | A PR description skill |
| `incident.md` | A bug triage skill |

**Simple lesson:** a template gives every file the same start. A final check makes sure no blank is left.

## Common Mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
| --- | --- | --- | --- |
| No output format | The agent will pick a good shape | List the exact headings | Every reply looks different |
| Changing heading words | "Bug fixes" and "Fixes" are the same | Use the same words every time | Scripts miss the section |
| Describing a format but not showing it | Rules are enough | Add one example line | The agent guesses the layout |
| Dropping empty sections | No content means no heading | Write "None" under it | Readers think it was forgotten |
| JSON for people | JSON is always better | Headings for people, JSON for programs | People struggle to read the reply |
| Leaving template blanks | Someone will notice | Check that no `{{...}}` is left | Broken files reach the code |

## Check Your Understanding

## Exercises

These exercises use real replies and real skill files.

Press **Check** when you are ready. Use **Show Hint** if you get stuck.

## What to Remember

- An output format lists the headings every reply must have.
- Use the same words and the same order every time.
- A field format says how one line must look.
- List the allowed values for fields like severity.
- Write "None" under an empty heading. Never drop it.
- Use headings for people and JSON for programs.
- One good example line shows the shape better than many rules.
- Templates give big files the same start. Check that no `{{...}}` is left.

Next: **Reference Files**. You will learn where to put long detail, so `SKILL.md` stays short.
