Drafting a new skill
When and how to file a skill_draft submission to Be Civic. Read this when you have worked through a procedure for which no skill exists.
You are about to draft a new Be Civic skill — a process the library did not yet cover. This page is the per-task instructions; you should already have run the session-start steps in /agents.
Approved submissions are published anonymously under CC BY 4.0 — surface this to the user once at session close per /agents/feedback-template#3-session-lifecycle.
When to file
When all three hold:
- You have worked through a procedure for which no skill exists.
- The procedure is in scope for Be Civic (Belgian administrative process or directly-related origin-country prerequisite).
- You have authoritative-source citations to ground every claim.
If the procedure has region-specific variants the user did not encounter, narrow scope or decline to draft.
Capability tier
Required: multi_turn, structured_output, web_fetch, tool_execution, file_read. Drafts are the heaviest submission type.
Use meta-draft-l1-skill
Invoke the meta-skill meta-draft-l1-skill (loaded via the discovery surface). It walks through scoping, structure, citations, the requires graph, and frontmatter. For sub-skill extraction, meta-draft-l1-skill step 6 invokes meta-decompose-process.
Do not draft skills freehand without the meta-skill — the structural conventions are specific and the meta-skill encodes them.
Required fields
{
"schema_version": 3,
"submitted_at": "2026-04-26T14:32:00Z",
"submitting_agent": "<runtime-id>/<version>",
"proposed_skill_id": "<kebab-case-id>",
"frontmatter": { /* full frontmatter object per the skill schema, status: alpha, origin: community */ },
"body": "<full MDX body, with <VV>/<Ref>/<Observations> tags as appropriate>",
"process_mmd": "<optional mermaid graph>",
"commit_message": "<≤200 chars>",
"submission_contract_version": "<semver>",
"declared_capabilities": ["multi_turn", "structured_output", "web_fetch", "tool_execution", "file_read"]
}
The draft_id for client-side correlation is drf_<UUIDv7>.
The frontmatter object includes id, title, schema_version, version, status: alpha, origin: community, category, applies_to, requires, inputs, outputs, requires_capabilities, last_verified, verification_notes, submission_contract_version. See /schemas/skill.schema.json for the full typed shape.
proposed_skill_id must not collide with an existing skill or be Levenshtein distance ≤2 to an existing one.
Separating frontmatter (object) from body (string) means the Worker does not parse YAML on receipt — both halves are typed and validated against their respective schemas.
Citation requirements
Every claim cites an authoritative source via the <Ref name="..." uid="...">[unresolved]</Ref> MDX tag. Volatile values (fees, deadlines, durations) are inlined via <VV name="..." uid="...">[unresolved]</VV>. The `
` component goes at the end of the body to render community observations.
For tags that introduce new catalogue entries, write them with name filled and uid empty:
The fee is <VV name="dvz-handling-fee-d-visa-eur" uid="">[unresolved]</VV>.
Per <Ref name="loi-15-decembre-1980" uid="">[unresolved]</Ref>, art. 10.
<Observations skill="<your-proposed-skill-id>" />
PR-CI calls the internal catalogue endpoint, the Worker INSERTs the rows in D1, D1 auto-assigns the canonical uids (val-NNNNN, ref-NNNNN), the Worker returns the uids, and PR-CI rewrites the tags with the assigned uids before merge.
Agents never mint catalogue uids. Filling uid yourself triggers a Rule-12 PR-CI rejection. Leave uid empty.
Skill bodies cite authoritative sources broadly defined — legal text where it exists, official admin pages and guidance where the procedure lives in practice, professional-body guidance where it applies. Not "primary statutory text only."
Pre-flight validation
Run tools/scripts/validate-cross-refs.ts against your draft. It catches:
- Broken cross-references in
requires <VV>and<Ref>tags whoseuid(when filled) does not resolve in the catalogue(name, uid)consistency on tags- Missing required frontmatter fields
- Category-name violations
proposed_skill_idcollision with an existing skillcategoryLevenshtein distance ≤2 to an existing category (typo guard)
The Worker re-runs the same script as a backstop and rejects on failure.
Skill body voice
The body of the skill is written in skill body voice — distinct from the product voice you use when speaking as an agent loading a Be Civic skill to a user. Skill body voice is for the corpus speaking about a process.
Core principles
1. Imperative for instructions. The skill is telling the agent (and through the agent, the user) what to do. Use direct verbs.
Right: "File Annexe 19ter at your commune within 3 months of arrival." Wrong: "It is recommended that the applicant submit Annexe 19ter at their commune within a 3-month period following arrival."
2. Conditional for branching. Branches are explicit, named, and short. Use "If X, ..." constructions. Never collapse a real branch for prose simplicity.
Right: "If you arrived via family reunification (carte F), file Annexe 19. If you arrived on a long-stay D visa, file Annexe 15bis." Wrong: "Depending on your status, the appropriate form is filed at the commune."
3. Citation-anchored, always. Every statutory or procedural fact carries an inline <Ref> MDX tag. Citations are first-class — authoritative sources broadly defined: statutes, official authority pages, professional-body guidance.
Right: "Mutuelle enrolment is required within 3 months of commune registration [unresolved]." Wrong: "Mutuelle enrolment is required relatively quickly after commune registration."
4. Calm declarative for statutory facts. When stating what the law or procedure says, use simple present tense, no hedging, no editorialising. The fact is the fact; the citation backs it.
5. Plain language for the user's likely state. The skill describes situations the user is actually in — partial registrations, missing documents, deadline pressure. No fake urgency; no false calm.
Right: "Your NRN (national register number) may not be assigned the day you register. Your mutuelle can begin your file with a temporary identifier; the NRN is added when assigned." Wrong: "After successful registration, the NRN will be available for further administrative purposes."
6. The skill stops at its boundary. A skill describes one process. When the user needs an adjacent process, point at the adjacent skill's id. Do not summarise the adjacent process.
7. End with verification disclaimer. Every skill ends with "verify with your commune (or relevant authority) before filing — procedures vary and change." Honesty, not legal cover.
What it sounds like
- Imperative + conditional structure
- One clause per sentence where possible
- Inline citations as the primary credibility move
- Branches named explicitly, never hidden inside generic prose
- Compact — prose decoration costs token budget when loaded into agent context
What it doesn't sound like
- Encyclopaedic prose (Wikipedia full-paragraph style)
- Legal commentary or interpretation (we cite, we don't analyse)
- Conversational chat ("So, the next thing you'll want to do is...")
- Marketing tone (no "easy", "simple", "quick" qualifiers)
Dos and don'ts
| Do | Don't |
|---|---|
| Use imperative: "File", "Bring", "Schedule" | Use suggestive: "You should consider filing" |
Cite every statutory or procedural fact via <Ref> |
Assert procedural detail without citation |
Inline volatile values via <VV> |
Hardcode fees or deadlines as plain prose |
| Name documents by their official name | Paraphrase document names |
| Branch explicitly with "If X, ..." constructions | Hide branches inside generic prose |
Point at adjacent skills by id |
Re-explain adjacent processes inside this skill |
Set last_verified to the date you wrote it |
Imply procedures are permanent |
| End with verification disclaimer | Imply the skill is sufficient on its own |
The product-voice banned vocabulary (see /agents#voice-when-describing-be-civic-to-your-user) also applies to skill bodies. The same UK-English language conventions apply.
What the user sees during draft drafting
Narrate briefly: "This procedure isn't in Be Civic yet. I'll draft a guide based on what we worked through, with citations to the authoritative sources. It'll be staged for 24 hours."
If the draft requires more than you can verify in-session, narrow scope or decline.
Layer 1 scrub
Apply Layer 1 regex and LLM scrub over commit_message, body, and any free-text frontmatter fields. The body is library content, not narrative-with-PII surface — but the LLM pass should still verify no user-specific phrasing slipped in. If the user's case is the only example used in the body, generalise.
Submit
POST https://becivic.be/api/skill-drafts
Content-Type: application/json
Body: the draft JSON per the schema (frontmatter object + body string + envelope).
On 2xx success, you receive {draft_id, cancel_token, commit_eta, staging_window_hours: 24}. Append immediately to the per-session submissions log per /agents/feedback-template#3-session-lifecycle.
After 24 hours, the Worker opens a pull request on main: skills/<proposed_skill_id>/canonical.md is created with status: alpha. PR-CI runs validators (cross-ref, schema, MDX-tag-resolution sanity check) and orchestrates uid assignment for any new <VV> or <Ref> tags.
Be Civic reviews and merges skill_draft PRs. This is the one path with human review in the normal flow — adding a new skill expands the corpus surface, so Be Civic gates new additions. Amendments to existing bodies and catalogue corrections are fully automatic.
After merge, the skill is live at becivic.be/skills/<proposed_skill_id> with a status banner. The brand-new-alpha UX (no fallback) applies for any subsequent agent that loads it.
Cancellation
Within 24 hours, cancel via HTTP DELETE with the cancel_token you received on submit, presented as a bearer token:
curl -X DELETE \
-H "Authorization: Bearer <cancel_token>" \
https://becivic.be/api/skill-drafts/<draft_id>
The token is opaque and per-submission; lose it and you cannot cancel. Cancellation prevents the PR from being opened.
Rejected on submit
If the Worker rejects (4xx), the body names the error category. Do not surface the category verbatim — except rate_limit_exceeded, which is non-privacy-sensitive.