Skip to content
Felspar
Esc
↑↓navigate↵open⌘Jpreview
On this page

Pack draft format

The felspar.pack-draft JSON format that check_pack and propose_pack accept - purpose, subjects, questions, outcomes, escalations and test cases - with every field and limit.

A pack draft describes one job: what it is for and when to use it, what each case is about, the questions an agent answers from evidence, the outcomes, the rules that pick an outcome, where undecided cases escalate, and test cases. check_pack and propose_pack take it, together with the source_object_id of the document it quotes. Felspar locates every quote and builds the full proposal from it, so nobody writes fingerprints, passages or classifier settings by hand.

The same guide is available to any assistant through the get_pack_guide tool.

Format versions

schema Adds Status
felspar.pack-draft/v2 A required purpose, plus useWhen, notFor, owner, subjects, subject and escalations Current
felspar.pack-draft/v1 Number and date questions with quoted thresholds, and scoring Accepted; numbers, dates and scoring are in preview
felspar.pack-draft/v0 Answer-choice questions, outcomes, rules and test cases Accepted

Every v0 draft is also a valid v1 draft, and v2 is v1 with a required purpose. Subjects, escalations and the job fields are optional before v2. A draft that doesn’t use them builds exactly the same release as before.

Shape

A fictional support-desk policy, drafted as v2:

{
  "schema": "felspar.pack-draft/v2",
  "job": "triage-ticket",
  "purpose": "<quote: why the job exists and what it resolves>",
  "useWhen": ["<quote>"],
  "notFor": ["<quote>"],
  "owner": "<quote: the accountable role>",
  "subjects": [
    { "id": "ticket", "definition": "<quote>", "identifier": "help desk ticket number", "example": "48213",
      "relationships": [
        { "name": "customer", "subject": "customer", "cardinality": "one", "definition": "<quote>" }
      ] },
    { "id": "customer", "definition": "<quote>", "identifier": "account ID", "example": "cus-9f2" }
  ],
  "subject": "ticket",
  "escalations": [
    { "id": "human-review", "quote": "<quote>" },
    { "id": "incident-review", "quote": "<quote>" }
  ],
  "evidenceKinds": ["ticket", "account"],
  "maxEvidenceAgeDays": 30,
  "questions": [
    {
      "key": "topic",
      "meaning": "<quote: the question>",
      "answers": [
        { "value": "charge", "meaning": "<quote>", "inclusions": ["<quote>"], "exclusions": ["<quote>"], "examples": ["<quote>"] },
        { "value": "failure", "meaning": "<quote>", "examples": ["<quote>"] },
        { "value": "other", "meaning": "<quote>", "noneOfThese": true }
      ],
      "whereToLook": ["<quote>"]
    },
    {
      "key": "premium",
      "about": "customer",
      "meaning": "<quote>",
      "answers": [
        { "value": "yes", "meaning": "<quote>" },
        { "value": "no", "meaning": "<quote>" }
      ]
    }
  ],
  "outcomes": [
    { "id": "billing", "nextStep": "<quote: what to do next>" },
    { "id": "on-call", "nextStep": "<quote>", "escalate": "incident-review" },
    { "id": "general", "nextStep": "<quote>" }
  ],
  "whenUnresolved": { "quote": "<quote: what to do when nothing is decided>", "escalate": "human-review" },
  "attempts": { "max": 2, "escalate": "human-review" },
  "rules": [
    { "id": "charge", "meaning": "<quote>", "when": { "topic": "charge" }, "outcome": "billing" },
    { "id": "failure", "meaning": "<quote>", "when": { "topic": "failure" }, "outcome": "on-call" },
    { "id": "other", "meaning": "<quote>", "when": { "topic": "other" }, "outcome": "general" }
  ],
  "cases": [
    { "id": "invoice", "why": "<where the document says so>", "subject": { "id": "48213" },
      "facts": { "topic": "charge", "premium": "no" }, "expect": { "outcome": "billing", "rule": "charge" } },
    { "id": "outage", "why": "<where the document says so>",
      "facts": { "topic": "failure", "premium": "yes" },
      "expect": { "outcome": "on-call", "rule": "failure", "escalation": "incident-review" } }
  ]
}

Fields

The job

Field Required Rules
schema Yes "felspar.pack-draft/v2" (or v1, v0)
job Yes The job ID agents use, such as triage-ticket or review-nda
purpose Yes in v2 Quote: why the job exists and what it resolves
useWhen, notFor No 1 to 8 quotes each: when the document says to use the job, and when not
owner No Quote: the accountable role, only if the document names one
evidenceKinds Yes 1 to 8 kinds of evidence that count, such as ticket, contract or company-site. These become the source classes agents send.
maxEvidenceAgeDays Yes 1 to 3,650. How old evidence may be.

Agents see purpose, useWhen, notFor and the subject first, in list_jobs and get_job_requirements, and pick a job by them.

Subjects

Field Required Rules
subjects No 1 to 16 subject types: each kind of record the document talks about
subjects[].id Yes The record’s name in the document, such as ticket or contract
subjects[].definition Yes Quote: what the record is
subjects[].identifier For provided How its ID is written, such as “the contract ID in the matter system”. Needed when the job’s cases use the record’s own ID, and for any subject a relationship points to.
subjects[].example With identifier One ID, written as Felspar keeps it (lowercase for case-insensitive)
subjects[].match No exact (default) or case-insensitive
subjects[].identity No How a case gets its ID: provided, fields, content or issued (below). Without it, a subject with an identifier is provided and one without is issued.
subjects[].relationships No Up to 16, each { name, subject, cardinality, required?, definition }: subject is another declared subject, cardinality is one or many, required is true when the document says a decision needs that record, and definition is a quote
subject No The subject type this job decides about
questions[].about No The relationship whose record a question’s evidence comes from
cases[].subject No { id }: decide this test case as that record

See Subjects and escalations for how agents send related records and what results carry.

Questions and answers

Field Required Rules
questions Yes 1 to 64
questions[].key Yes The question’s ID
questions[].meaning Yes Quote: the question
questions[].answers Yes, for answer-choice questions 2 to 64 answers
answers[].value Yes The answer’s ID
answers[].meaning Yes Quote: what the answer means
answers[].inclusions, exclusions, examples, edgeCases No Up to 8 quotes each
answers[].noneOfThese No true on at most one answer per question: the answer for text that clearly says something outside the list
questions[].askOnlyWhen No Conditions under which the question applies
questions[].whereToLook No Up to 8 quotes: where the policy says to look

Outcomes, escalations and rules

Field Required Rules
outcomes Yes 1 to 64, each { id, nextStep, escalate? } with nextStep a quote and escalate an escalation ID
escalations No 1 to 16, each { id, quote }: a hand-off the document names, such as legal-review
whenUnresolved Yes Quote: what an agent does when nothing is decided. Or { quote, escalate } to name the hand-off too.
attempts.max No 1 to 10, default 3: how many decisions an agent may ask for on one undecided case
attempts.escalate No The escalation once a case has used its attempts (otherwise whenUnresolved’s)
rules Yes 1 to 256, in order: the first that matches decides
rules[].when Yes Question keys mapped to one answer, or a list of 2 to 64 answers meaning “any of these”

Test cases

Field Required Rules
cases Yes 1 to 200 test cases
cases[].facts Yes Question keys mapped to answers
cases[].expect Yes { outcome, rule, escalation? }: the outcome the policy says, the rule that should decide it, and the escalation the document says it hands off to

Identifiers use lowercase letters, digits, - and _, starting with a letter or digit. Quotes are at most 4,000 characters. Subject examples and case IDs use letters, digits and . _ : @ -, up to 200 characters.

Rules Felspar enforces

  • Meaning comes only from the document. Every meaning, nextStep, whenUnresolved, purpose, useWhen, notFor, owner, subject and relationship definition, escalation quote, inclusion, exclusion, example and where-to-look is an exact quote from read_source, copied character for character (keep escapes such as \_). A quote must appear exactly once in the document. An answer’s quote is first looked for, as whole words, inside its question’s quote, so an option such as “yes” can be quoted where the question lists it.
  • Rules are in order. The first rule that matches decides.
  • Conditional questions. A question with askOnlyWhen is asked only when those answers hold. Every rule that uses it must repeat that exact condition.
  • Tests come from the document. Take each expectation from the policy, never from what the draft returns.
  • Don’t decide what the document leaves open. Report contradictions, missing values and undecided cases to the owner as gaps, with both quotes. If the document doesn’t say how a record is identified, which records a decision needs, or who reviews a held case, ask the owner; never invent one.
  • Escalations name a kind of review, such as human-review or compliance-review, never a tool, channel or person. The company’s own code decides what each one does.
  • Quote budget. One question’s quotes may come from at most 16 separate blocks of the document; quotes in the same list or table count once.

Findings

Beyond errors at a path, check_pack and propose_pack return completeness findings:

  • Blocking: an answer without a definition; a multiple-choice question without a “none of these” answer that a rule routes; a threshold without test cases on both sides of its edge. propose_pack refuses while any remain.
  • Warnings: answers without inclusions or examples; answers without exclusions; combinations of answers no rule decides; an evidence age the document doesn’t state; answers that describe an absence; “unknown” options; questions, outcomes or rules nothing uses or tests; escalations declared while whenUnresolved names none, so an undecided case has nowhere to go.

Some findings carry candidates: lines in the document that mention the answer and might supply the missing quote.

When the draft revises a job that already has a release, check_pack and propose_pack also return breaking: each escalation ID, subject type or relationship name the draft removes, and a changed job subject, with the number of agents that run the job. See Review and backtest.

Numbers, dates and scoring

These need felspar.pack-draft/v1 or v2 and are in preview. get_pack_guide has the full rules.

  • Number questions give a type: "number", a unit (a currency code, percent, or the noun a count is of, with unitWords), and a quoted meaning. Date questions give type: "date". Felspar reads both exactly from the agent’s excerpt, with no model, so they need no answers.
  • Thresholds in a rule name their bound and quote where the document states it: { "employees": { "lt": 500, "quote": "fewer than 500 employees" } }. A date bound can be a date, another date question plus days, or the decision date plus days. Every threshold needs test cases on both sides of its edge.
  • Scoring adds up quoted points per criterion; rules then become score bands (score: { gte, quote }) and gates (gate: true), and test cases give the expected total.

Output checks

When the document says what a written output (a reply, an email) must or must not say, outputChecks names the output, the outcomes that produce it, and its checks: exact wording it must contain (require) or must not (prohibit), the case’s own answer it must state (states), yes/no questions asked of each paragraph (ask), and the approved context an agent may write from. Each check quotes the document. After release, a decided result lists the outputs its outcome asks for, and agents check what they wrote with check_output.

Identity modes

A subject’s identity says how a case gets its ID when the record has none of its own:

identity Means Checked
{ "mode": "provided" } The record’s own ID The subject needs identifier and example
{ "mode": "fields", "fields": [{ "name", "identifier", "example", "match"? }] } Named values the job collects, such as an email address and a requisition number, normalized by each field’s match (default exact) and hashed in name order 1 to 8 fields with unique names; each example written as its match keeps it
{ "mode": "content", "question": "<key>" } The text one question judges is the case question is a question key in the job
{ "mode": "issued" } Felspar issues an ID on the first decision Nothing else

Without identity, a subject with an identifier is provided and one without is issued. A v2 job without a subject is issued; a v0 or v1 job without one keeps the caller’s own ID. A subject that a relationship points to is always sent by its own ID, so it must be provided, with an identifier. See Subjects and escalations for what agents send and what results carry.

Was this page helpful?