CALIBER
Quickstart

Cookbook 02 · Foundations

Precision Skills

Deterministic triggering + portable packaging — a skill that fires only when it should.

FoundationsStarter25–40 min
What you build. A reusable response skill (support-tone-and-citation) that activates on support queries but stays silent on engineering ones, and exports cleanly as a portable package (Download ZIP).
Surfaces: Skills Observability
What you learn
  • Author a skill with a tight trigger summary (the selector reads it)
  • Render-preview variable substitution
  • Run deterministic trigger tests (positive vs negative)
  • Export a portable skill package (Download ZIP)
  • Tighten the summary first when a negative query mis-fires

Implementation flow

flowchart TD
  A[Author skill: summary + content] --> R[Render Preview]
  A --> T{Trigger Tests}
  T -->|positive queries| Y[is_selected = true]
  T -->|engineering queries| N[is_selected = false]
  A --> X[Export ZIP: portable package]

Step-by-step UI only

Each step shows the exact navigation path, the fields to fill, the button to click, and a snapshot of the CALIBER screen you'll be on.

  1. Library › Skills › Build Skill creates · skill: support-tone-and-citation support-tone-and-citation.md ↓
    Create the skill that holds your customer-support response policy (tone, citations, escalation). A skill is a reusable behavior an agent can select; the one-line summary is the trigger text the selector reads, so keep it narrow. Clicking Build Skill opens the guided wizard (Identity → Content → … → Review & Create). Names must be kebab-case and must not start with claude or anthropic.
    Fill in
    Namesupport-tone-and-citation
    Categorysupport (or the closest option)
    Tagssupport, tone, citation, escalation, customer-facing
    SummaryVoice and citation rules for customer-facing support replies (billing, refunds, account, how-to); NOT for engineering, code, API, infra, or schema questions.
    Contentpaste the body of support-tone-and-citation.md (everything below the YAML frontmatter, starting at You shape how a support reply is written...)
    Click Create Skill
    You'll see: The skill is created at v1 and its workspace opens with stage tabs (Author, Render Preview, Trigger Tests, Scenario Sets, Runs, Bind).
    Screen snapshot
    caliber · Library › Skills › Build Skill
    SkillsBuild Skill
    Create Skill
  2. Library › Skills › support-tone-and-citation › Author creates · skill version: support-tone-and-citation
    Confirm the summary and content saved correctly, and tweak them here if needed. Editing on the Author stage is what updates the skill, so this is where the trigger summary and the policy body live.
    Fill in
    Summary / Contentverify the trigger summary and the policy body match the asset; adjust wording if needed
    Click Save changes
    You'll see: A success toast and the updated summary/content become the live skill definition.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Author
    SkillsAuthor
    Save changes
  3. Library › Skills › support-tone-and-citation › Render Preview render-vars.json ↓
    Check that the skill's template variables fill in cleanly. Render Preview substitutes {{ vars }} and reports any it could not resolve — supply all three required variables so nothing is left unresolved.
    Fill in
    Variablespaste the variables object from render-vars.json (supplies user_message, audience, and policy_context)
    Click Render Skill
    You'll see: A rendered reply that cites [KB-1042]/[KB-1007] and avoids a fixed date, with unresolved_variables reported as empty ([]).
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Render Preview
    SkillsRender Preview
    Render Skill
  4. Library › Skills › support-tone-and-citation › Trigger Tests creates · trigger results: positive cases T01–T06 trigger-cases.jsonl ↓
    Run the positive trigger cases — customer-facing support phrasing that should select this skill. Trigger testing is deterministic (no LLM): it returns is_selected, selection_score, and selection_reason. Run rows T01–T06 from the cases file, one at a time.
    Fill in
    user_messagefor each positive row, paste its user_message (e.g. How do I get a refund for the duplicate charge on my account?) from trigger-cases.jsonl
    artifact_typethe row's artifact_type (e.g. support_reply)
    session_goalthe row's session_goal (e.g. Draft a customer-facing support reply)
    Click Check selection
    You'll see: Each positive case returns is_selected = true with a selection score and a human-readable reason.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Trigger Tests
    SkillsTrigger Tests
    Check selection
  5. Library › Skills › support-tone-and-citation › Trigger Tests creates · trigger results: negative cases T07–T12
    Now run the negative cases — engineering/code/API/infra/schema queries that should not select this support skill. This proves the skill is narrow and won't fire on the wrong work. Run rows T07–T12.
    Fill in
    user_messagefor each negative row, paste its user_message (e.g. How do I rotate the JWT signing key without invalidating active sessions?) from trigger-cases.jsonl
    artifact_typethe row's artifact_type (e.g. code_answer)
    session_goalthe row's session_goal (e.g. Implement secure key rotation)
    Click Check selection
    You'll see: Each negative case returns is_selected = false. Tally false-positives + false-negatives across all 12 cases — the gate is trigger accuracy ≥ 0.95.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Trigger Tests
    SkillsTrigger Tests
    Check selection
  6. Library › Skills › support-tone-and-citation › Author creates · skill update: tightened summary
    If any negative case wrongly selected (a false positive), sharpen the summary first — the summary/trigger text dominates selection, so tighten it before touching the long-form content. (Skip this edit if all 12 cases already passed.)
    Fill in
    Summarytighten the boundary wording, e.g. add explicit exclusions like ...NOT for engineering, code, API, infra, database, schema, or internal-tooling questions.
    Click Save changes
    You'll see: The updated summary is saved; re-running the Trigger Tests now shows the previously mis-selected negative case returning is_selected = false.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Author
    SkillsAuthor
    Save changes
  7. Library › Skills › support-tone-and-citation › Runs creates · pinned baseline: trigger run
    Save a passing trigger run as the baseline so the current stable trigger behavior is the reference for future changes. The Runs stage records durable runs and lets you pin one as the baseline.
    Click Set as baseline
    You'll see: The run gets a Baseline marker in the run history, recording the known-good positive/negative trigger decisions.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Runs
    SkillsRuns
    Set as baseline
  8. Library › Skills › support-tone-and-citation › Runs creates · calibration job id (queued)
    Queue a calibration job to refine the skill (the agent-free optimizer auto-provisions the target — no agent to pick). It runs in the background, so capture the queued job id rather than waiting for it to finish inline.
    Click Calibrate
    You'll see: A confirmation reading "Calibration queued — job {job_id}."; the job runs in the background. Note the job id.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Runs
    SkillsRuns
    Calibrate
  9. Skill detail page (/skills/<skill_id>) creates · skill package: support-tone-and-citation.zip
    Export the skill as a portable package. Download ZIP lives only on the standalone skill detail page, a separate surface from the in-page Workspace (clicking a skill in the Skills list opens the Workspace stages, which have no Download ZIP). Navigate directly to /skills/<skill_id> in the address bar — copy the skill's id from the Workspace and paste it into the URL. Download ZIP produces a self-contained bundle (SKILL.md + agents/openai.yaml + bundled resources) you can move between workspaces — this is the portability artifact the lab is proving.
    Click Download ZIP
    You'll see: A .zip file downloads containing SKILL.md and the OpenAI agent manifest. Inspect it to confirm the summary, content, and resources round-trip out cleanly.
    Screen snapshot
    caliber · Skill detail page (/skills/&lt;skill_id&gt;)
    SkillsSkill detail page (/skills/&lt;skill_id&gt;)
    Download ZIP
  10. Library › Skills › support-tone-and-citation › Bind creates · skill binding: support-tone-and-citation
    Bind the skill to an agent (or a workflow node) so it can be used at runtime. Binding makes the skill available to the chosen target without any extra registration.
    Fill in
    Bind targetchoose an agent (or workflow node) to attach the skill to
    Click Bind
    You'll see: A confirmation that support-tone-and-citation is now bound to the selected target, ready for use.
    Screen snapshot
    caliber · Library › Skills › support-tone-and-citation › Bind
    SkillsBind
    Bind

Assets (copy-paste)

The exact files this cookbook uses — copy each into the matching field. Source: docs-site/cookbooks/02-skill-trigger-packaging-lab/assets/.

assets/skills/support-tone-and-citation.md
---
name: support-tone-and-citation
summary: "Voice and citation rules for customer-facing support replies (billing, refunds, account, how-to); NOT for engineering, code, API, infra, or schema questions."
category: support
tags: [support, tone, citation, escalation, customer-facing]
render_variables: [user_message, audience, policy_context]
---

You shape how a support reply is written. You do NOT decide the underlying
policy outcome (refund approved/denied, account unlocked, etc.) — that decision
arrives in `{{ policy_context }}`. Your job is to deliver it to the customer in
the right voice, with the right citations and the right escalation hint.

Apply this only to **customer-facing support replies**. If the request is an
engineering, code, API, infrastructure, database, or internal-tooling question,
this skill does not apply — defer to the relevant engineering skill instead.

## Tone rules

- Stay calm and plain-spoken. Acknowledge the customer's situation in one
  sentence before getting to the answer; do not gush or over-apologize.
- Write for `{{ audience }}`. A non-technical customer gets no product
  internals; a technical contact may get precise field/feature names but still
  no internal system names.
- No internal jargon. Never expose internal team names, ticket/queue ids,
  service or component names, codenames, or model/provider names.
- No over-promising. Do not commit to dates, amounts, or outcomes that are not
  already stated in `{{ policy_context }}`. If something is "under review", say
  exactly that — never "this will be fixed" or "you'll get a full refund"
  unless `{{ policy_context }}` says so.
- One ask at a time. If you need information from the customer, request a single
  clear thing.

## Citation hints

- When you assert a fact, a policy, or an eligibility rule, cite the supporting
  knowledge-base article by id (e.g. `[KB-1042]`) inline right after the claim.
- Only cite article ids that appear in `{{ policy_context }}`. Never invent a
  KB id, and never cite an id you were not given.
- If `{{ policy_context }}` contains no supporting article for a claim, soften
  the claim to what you can support and add: "I'm confirming the exact policy
  and will follow up." Do not fabricate a citation to fill the gap.

## Escalation hints

- Escalate (hand to a human/specialist) when `{{ policy_context }}` is empty or
  contradictory, when the customer is at financial or security risk, or when the
  resolution requires an action this reply cannot itself authorize.
- When escalating, tell the customer plainly that you are routing them to
  someone who can help and set a realistic next-step expectation — without
  naming the internal team or queue.

## Output

Produce only the customer-facing reply text. No headers, no internal notes, no
JSON. End with a single concrete next step or a clear closing line.

Audience: {{ audience }}
Policy context (decision + any KB article ids to cite):
"""
{{ policy_context }}
"""
Customer message:
"""
{{ user_message }}
"""

Write the reply now.
assets/dataset/render-vars.json
{
  "variables": {
    "user_message": "Hi — I was charged twice for my Team plan this month and I'd like one of the charges refunded. This is really frustrating.",
    "audience": "non-technical customer",
    "policy_context": "Decision: duplicate-charge refund APPROVED for the second charge; refunds post in 5-7 business days. Cite [KB-1042] (duplicate-charge refunds) and [KB-1007] (refund timing). Do not promise a specific calendar date."
  },
  "expected": {
    "unresolved_variables": []
  },
  "notes": "Paste the `variables` object into Skills -> Render Preview (POST /skills/{id}/test-render {variables:{...}}). All three render_contract variables (user_message, audience, policy_context) are supplied, so the response's `unresolved_variables` must be []. The rendered output should read as a calm reply that cites [KB-1042]/[KB-1007] and avoids a fixed date."
}
assets/dataset/trigger-cases.jsonl
{"id": "T01", "tags": ["positive"], "inputs": {"user_message": "How do I get a refund for the duplicate charge on my account?", "artifact_type": "support_reply", "session_goal": "Draft a customer-facing support reply"}, "expectations": {"is_selected": true}}
{"id": "T02", "tags": ["positive"], "inputs": {"user_message": "A customer is upset about a billing delay — draft a calm response that references our policy.", "artifact_type": "support_reply", "session_goal": "Reply to an upset billing customer"}, "expectations": {"is_selected": true}}
{"id": "T03", "tags": ["positive"], "inputs": {"user_message": "Customer can't access their account after a lockout and wants to know what to do next.", "artifact_type": "support_reply", "session_goal": "Help a customer with account lockout"}, "expectations": {"is_selected": true}}
{"id": "T04", "tags": ["positive"], "inputs": {"user_message": "Write a reply explaining why we can't approve the refund, but keep the tone friendly.", "artifact_type": "support_reply", "session_goal": "Decline a refund politely"}, "expectations": {"is_selected": true}}
{"id": "T05", "tags": ["positive"], "inputs": {"user_message": "How do I tell the customer their plan downgrade takes effect next billing cycle?", "artifact_type": "support_reply", "session_goal": "Explain a plan downgrade to a customer"}, "expectations": {"is_selected": true}}
{"id": "T06", "tags": ["positive"], "inputs": {"user_message": "Customer emailed asking where to find their invoice — draft a helpful support response.", "artifact_type": "support_reply", "session_goal": "Answer a customer how-to about invoices"}, "expectations": {"is_selected": true}}
{"id": "T07", "tags": ["negative"], "inputs": {"user_message": "How do I rotate the JWT signing key without invalidating active sessions?", "artifact_type": "code_answer", "session_goal": "Implement secure key rotation"}, "expectations": {"is_selected": false}}
{"id": "T08", "tags": ["negative"], "inputs": {"user_message": "Fix this Python stack trace: KeyError: 'order_id' in handler.py line 42.", "artifact_type": "code_answer", "session_goal": "Debug a backend exception"}, "expectations": {"is_selected": false}}
{"id": "T09", "tags": ["negative"], "inputs": {"user_message": "What's the right database index strategy for our orders table given these query patterns?", "artifact_type": "code_answer", "session_goal": "Design a database index strategy"}, "expectations": {"is_selected": false}}
{"id": "T10", "tags": ["negative"], "inputs": {"user_message": "Generate a SQL migration plan for the schema changes in this PR.", "artifact_type": "code_answer", "session_goal": "Plan a schema migration"}, "expectations": {"is_selected": false}}
{"id": "T11", "tags": ["negative"], "inputs": {"user_message": "Summarize deployment latency metrics for the engineering team.", "artifact_type": "report", "session_goal": "Report infra metrics to engineers"}, "expectations": {"is_selected": false}}
{"id": "T12", "tags": ["negative"], "inputs": {"user_message": "Write a unit test for the refund-eligibility function in billing.py.", "artifact_type": "code_answer", "session_goal": "Add test coverage to the billing module"}, "expectations": {"is_selected": false}}

Evaluation & quality gates

Quality gateTarget
Trigger accuracy≥ 0.95 (false-pos + false-neg counted)
Portable exportDownload ZIP yields a self-contained SKILL.md + agent manifest
Developer notes & gotchas
  • Selection scoring is deterministic (no LLM) — this is the precision check; there is no LLM judge here.
  • Skill names are kebab-case and must not start with claude/anthropic.
  • Calibrate enqueues a background job; Scenario Sets is scaffolded — drive cases through Trigger Tests + Runs.

CALIBER : Contextual Adaptive Lifecycle for Intelligent Build, Evaluation, and Refinement — Cookbooks — every recipe is UI-implementable on the shipped platform. Source + assets under docs-site/cookbooks/<nn>-…/. Regenerate with python3 docs-site/cookbooks/training/build.py.