AI Skill Report Card

Designing System One AI Workflows

A-83·Sep 17, 2026·Source: Extension-page
YAML
--- name: designing-system-one-ai-workflows description: Guides the design of AI-powered software using TypeSafe's System One model, where code owns control flow and AI handles narrow, typed, atomic judgments over unstructured data. Use when building software that needs AI-assisted decisions (classification, extraction, validation, routing) but must remain deterministic, auditable, and composable rather than agentic; when decomposing broad AI judgments into atomic questions; or when deciding how to combine model outputs with confidence-based routing. ---
14 / 15

Don't ask an AI to "handle" a task end-to-end. Instead:

  1. Write the workflow as normal code (control flow, branching, side effects).
  2. Wherever a decision requires interpreting unstructured input, replace that step with one or more atomic, typed questions.
  3. Send only the state each question needs.
  4. Run all independent questions in parallel in a single request.
  5. Combine answers with deterministic code (weighted sums, rules, thresholds) and route on confidence.
Python
# Bad: one broad AI judgment hides many sub-decisions {"is_spam": {"type": "noul", "instructions": "Is `message` spam?"}} # Good: decomposed, atomic, inspectable judgments { "requests_credentials": {"type": "noul", "instructions": "Does `message.body` ask for a password or login credential?"}, "creates_time_pressure": {"type": "noul", "instructions": "Does `message.body` pressure the recipient to act quickly?"}, "sender_identity_mismatch": {"type": "noul", "instructions": "Does the org in `message.sender.display_name` conflict with `message.sender.email`?"} }

Combine in code:

Python
answers = response.answers spam_score = ( 0.4 * answers["requests_credentials"].noul + 0.3 * answers["creates_time_pressure"].noul + 0.3 * answers["sender_identity_mismatch"].noul )
Recommendation
Add a concrete full input/output example showing actual JSON request/response with the 'noul' type schema so readers understand the wire format without guessing
14 / 15

Progress:

  • Step 1: Identify deterministic parts of the workflow — keep them in code
  • Step 2: Identify the minimum state each remaining decision needs
  • Step 3: Decompose each broad judgment into narrow, atomic, typed questions
  • Step 4: Add structure (nested paths, criteria objects) where ambiguity exists
  • Step 5: Batch all independent questions into one parallel request
  • Step 6: Compose answers in code (rules, weighted sums, or as ML features)
  • Step 7: Route on confidence — auto-act, review, or escalate

Step 1: Use code when you can

Deterministic rules (dates, thresholds, math, lookups) belong in code, not in a model call.

Python
days_overdue = (today - invoice.due_date).days if days_overdue > 30: route_to_collections(invoice)

Never use an agentic while-loop where a plain software workflow suffices — every loop iteration is a chance to go off the rails.

Step 2: Decompose the input state

Send only the fields relevant to the current questions. Don't rely on model world-knowledge when your own data source has the authoritative answer (e.g., pass in refund_policy text rather than expecting the model to know it).

Step 3: Use structure in the input state

Use nested JSON for state. Point questions at exact paths with backticks (e.g., `support.tickets[0].message`) to remove ambiguity about what's being evaluated.

Step 4: Decompose the questions (most important step)

Never ask one broad question that hides multiple judgments (e.g., "is this spam?", "is this tool trace correct?"). Instead, ask one atomic question per property:

  • Each question should test exactly one condition.
  • Each question should be independently answerable without depending on another question's answer.
  • Prefer noul (boolean-like probability), choice, or score types depending on the judgment shape.

Step 5: Use structure in the questions

When instructions or criteria need multiple kinds of guidance (what it is, what it's not, examples), use objects/arrays with named fields instead of one dense prose string:

JSON
{ "card_help_topic": { "type": "choice", "instructions": {"question": "...", "focus": "..."}, "criteria": { "option_a": {"what": "...", "not_for": "...", "examples": ["..."]}, "option_b": {"what": "...", "not_for": "...", "examples": ["..."]} } } }

Use identical field names across options/criteria so the model can compare them directly. Keep short, unambiguous questions as plain strings.

Step 6: Ask a lot of questions per request

Batch many narrow questions about the same state into a single request. They evaluate in parallel — decomposition does not add latency or round trips.

Step 7: Combine question outputs in code

Python
quality = ( 0.4 * answers["answers_request"].noul + 0.4 * answers["citations_are_supported"].noul + 0.2 * (1 - answers["contradicts_context"].noul) )

If training a downstream classical ML model, use these probabilities as input features.

Step 8: Route on uncertainty

Python
answer = response.answers["card_help_topic"] if answer.confidence < 0.8: route_to_human_review(ticket) else: route_to_handler(answer.choice, ticket)

Calibrate thresholds by plotting confidence against accuracy on real data.

Recommendation
Fix the typo 'noul' vs intended type name consistency check, and clarify what 'noul' stands for on first use
16 / 20

Example 1: Spam detection Input: One broad question — "is_spam": "Is message spam?" Output: Decomposed into requests_credentials, offers_unexpected_reward, creates_time_pressure, sender_identity_mismatch, link_domain_mismatch, disguises_link_destination — each independently scored, then combined in code into a single spam probability.

Example 2: Tool-call trace verification Input: One broad question — "tool_calls_are_correct": "Is trace.tool_calls correct?" Output: Decomposed per tool call into relevance, argument-schema conformance, argument-value correctness, and result-linkage checks (e.g., geocode_tool_is_relevant, geocode_arguments_match_schema, weather_uses_geocoded_coordinates), each independently verifiable.

Example 3: Support ticket triage Input: Incoming ticket + customer record. Output: Code short-circuits closed tickets deterministically; sends only relevant state (message, sender, open orders, policy) into parallel questions (topic choice, requests_credentials noul, sender_identity_mismatch noul, unexpected_reward noul, refund_requested noul); code composes results and routes by confidence.

Recommendation
Include a counter-example showing a bad outcome (e.g., a poorly decomposed question that caused a real failure) alongside the good ones for contrast
  • Treat System One calls as pure functions: typed in, typed probability distribution out — never free-form text to parse.
  • Keep each question atomic — if you're tempted to write "and" or "or" in an instruction, split it into two questions.
  • Give contrastive criteria (what vs not_for) with concrete examples for choice and noul question types.
  • Prefer parallel batched questions over sequential/chained model calls — no question's output should silently become another's hidden context.
  • Use probabilities/confidence as first-class values for thresholds, sorting, and weighted composition — not just as a pass/fail gate.
  • Reserve agent-style loops only for cases with a human actively supervising each step.
  • Broad questions: asking "is this X?" when X is actually five underlying judgments — makes tuning and debugging impossible.
  • Overloading context: dumping the entire object graph into state instead of the minimal relevant subset — invites context rot and irrelevant reasoning.
  • Chaining model calls sequentially when they could run in parallel — adds latency and creates hidden dependency chains between judgments.
  • Ignoring confidence: treating every answer as certain instead of routing low-confidence cases to review or a stronger model.
  • Using agent while-loops for tasks a deterministic workflow could express — unnecessary risk and cost.
  • Relying on model world-knowledge for facts your system already owns (policies, prices, dates) instead of passing them explicitly in state.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
16/20
Completeness
18/20
Format
14/15
Conciseness
13/15