From oxy-skills
Build and configure Oxy `.agentic.yml` files — multi-step FSM agents that ground questions in the semantic layer, generate SQL, execute it, and interpret results. Use when the user asks to create, edit, or troubleshoot an agentic analytics or app-builder agent, or to choose between `.agent.yml`, `.agentic.yml`, and `.workflow.yml`.
How this skill is triggered — by the user, by Claude, or both
Slash command
/oxy-skills:oxy-agentic-builderThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an expert at authoring Oxy `.agentic.yml` files. These configure a
You are an expert at authoring Oxy .agentic.yml files. These configure a
fixed-shape multi-step pipeline (clarify → specify → solve → execute →
interpret) that grounds a natural-language question in the project's
semantic layer, generates and runs SQL, and produces a structured answer.
| File | Use when |
|---|---|
.agentic.yml | Conversational data Q&A backed by the semantic layer; multi-turn, validator-driven |
.agent.yml | Single LLM call with custom tools (Python, raw SQL, file I/O); no semantic layer required |
.workflow.yml | Deterministic multi-step pipeline — no LLM reasoning between steps |
If the user's data already has views and topics, prefer .agentic.yml. If
they need an agent that runs a Python helper or reads arbitrary files,
use .agent.yml. If the steps are fixed and don't need an LLM to choose
between them, use .workflow.yml.
.agentic.yml files are short — almost everything is a sensible default.
A minimal file looks like this:
databases:
- warehouse
llm:
ref: claude-sonnet-4-6
context:
- ./semantics/**/*.view.yml
- ./semantics/**/*.topic.yml
The full annotated shape (every field is optional except databases in
practice — the agent has nothing to query without one):
instructions: | # Global system prompt for every state
... # Optional. Per-state additions go below.
databases: # Connector names from config.yml
- warehouse
context: # Globs resolved relative to this file
- ./semantics/**/*.view.yml # → semantic catalog
- ./semantics/**/*.topic.yml # → semantic catalog
- ./example_sql/*.sql # → injected into Solving prompt
- ./docs/*.md # → injected into Clarifying/Interpreting
- ./procedures/**/*.procedure.yml # → discoverable via search_procedures
llm: # Model + auth (defaults to Anthropic)
ref: claude-sonnet-4-6 # Reference an entry in config.yml
max_tokens: 8192
extended_thinking: # UI-toggled alternative preset
model: claude-opus-4-6
thinking: adaptive
thinking: adaptive # Default thinking mode for all states
states: # Per-state overrides (see below)
clarifying: { ... }
specifying: { ... }
solving: { ... }
executing: { ... }
interpreting: { ... }
validation: # Optional; defaults run all rules
rules:
specified: [ ... ]
solvable: [ ... ]
solved: [ ... ]
semantic_engine: # Optional; omit to use Oxy's bundled
vendor: cube # semantic layer
base_url: https://cube.example.com
api_token: "${CUBE_API_TOKEN}"
The runtime owns the state machine. You cannot add, rename, or remove states — only configure overrides on the ones below.
Clarifying → Specifying → Solving → Executing → Interpreting → Done
↑ ↑ ↑ ↑ ↑
└───────────┴───────────┴──────────┴─────────────┘
Diagnosing (back-edges)
| State | What it does | Tools available |
|---|---|---|
clarifying | Triage question type; resolve metrics/dimensions | search_catalog, search_procedures, ask_user |
specifying | Ground intent into a query spec; resolve joins | get_valid_dimensions, get_column_range |
solving | Generate SQL — skipped if semantic layer compiled it | explain_plan, dry_run |
executing | Run the query against the connector; validate results | (none — runs the SQL) |
interpreting | Turn results into natural language + chart | render_chart |
Skipped state: if clarifying produces an intent the semantic layer
can compile directly, solving is dynamically skipped and the spec goes
straight to executing. Do not write instructions: that assume the LLM
authors SQL — it may never see the prompt.
Back-edges: when a validator fails (see validation: below), the
solver enters diagnosing, picks a recovery target, and re-enters the
upstream state. Retries do not anchor on the previous failure — generate
fresh from the spec.
instructionsA string injected into every state's system prompt. Use it for stable
context: persona, dialect quirks, currency/locale, semantic-layer
conventions ("MRR = the monthly_recurring_revenue measure"). Keep
state-specific guidance in the per-state instructions: instead.
databasesA list of names referencing entries in the project's config.yml. The
HTTP layer resolves these to live connectors. All Oxy-supported types
work (DuckDB, Postgres, BigQuery, Snowflake, ClickHouse). Without a
database the pipeline has nothing to execute against.
contextGlobs resolved relative to the .agentic.yml's directory, bucketed by
extension at load time:
| Extension | Where it goes |
|---|---|
.view.yml / .view.yaml | Semantic catalog |
.topic.yml / .topic.yaml | Semantic catalog |
.sql | Example queries injected into Solving's prompt |
.md | Domain docs injected into Clarifying / Interpreting |
.procedure.yml / .yaml | Indexed for the search_procedures tool |
Other extensions are silently ignored. Use a wide enough glob —
./semantics/**/* — to catch the full catalog rather than enumerating
files.
llm| Field | Type | Notes |
|---|---|---|
ref | string | Model entry from config.yml; vendor/key/base_url inherit from that entry. |
vendor | enum | anthropic (default) | openai | openai_compat |
model | string | Overrides the model resolved from ref. |
api_key | string | Falls back to ANTHROPIC_API_KEY / OPENAI_API_KEY. |
base_url | string | Proxy / Responses API base / OpenAI-compat root. |
max_tokens | u32 | Defaults to 4096. |
thinking | see below | Default thinking mode for all states; takes precedence over top-level. |
extended_thinking | { model, thinking } | Preset activated by the UI's "extended thinking" toggle. |
Prefer ref: over inline credentials. The model entry centralises auth
so multiple agents share one secret.
thinkingThree forms accepted:
thinking: adaptive # shorthand
thinking: disabled # shorthand — bare or quoted both work
thinking: "disabled" # equivalent to bare form
thinking: effort:low # OpenAI o-series shorthand (low|medium|high)
thinking: # explicit budget (Anthropic)
budget_tokens: 10000
thinking: # OpenAI o-series map form
effort: medium
Per-state overrides accept the same forms. disabled is a string
identifier — bare disabled and quoted "disabled" are both accepted.
The bare boolean false is rejected; never write thinking: false.
statesEach key matches a pipeline stage by snake_case name. Legal keys:
clarifying, specifying, solving, executing, interpreting.
Unknown keys are silently ignored — typos cost nothing visible at parse
time, so spell carefully.
Per-state fields:
| Field | Type | Meaning |
|---|---|---|
instructions | string | Appended to the state's system prompt, on top of the global instructions:. |
thinking | (see above) | Overrides the global thinking config for this state only. |
max_retries | u32 | Cap on tool-use rounds before the state fails into Diagnosing. |
model | string | Replaces the model ID for this state. Vendor / key / base_url are inherited. |
Common pattern: a cheap model for clarifying, a powerful model for
solving, and thinking: disabled on interpreting to avoid burning
tokens on prose.
validationWhen the section is absent, every built-in rule runs with defaults. When it's present, only the rules you list are evaluated. Stages and rule names are fixed by the runtime:
| Stage | Rule |
|---|---|
specified | metric_resolves, join_key_exists, filter_unambiguous |
solvable | sql_syntax (dialect: …), tables_exist_in_catalog, spec_tables_present, column_refs_valid, timeseries_order_by_check |
solved | non_empty, shape_match, no_nan_inf, outlier_detection (threshold_sigma, min_rows), timeseries_date_check, truncation_warning, null_ratio_check (threshold), duplicate_row_check (max_duplicate_ratio) |
Each rule entry takes name, enabled (defaults to true), and any
rule-specific params:
validation:
rules:
solvable:
- name: sql_syntax
dialect: postgresql # generic | ansi | postgresql | mysql
# | bigquery | duckdb | snowflake
solved:
- name: outlier_detection
threshold_sigma: 5.0
min_rows: 4
- name: null_ratio_check
threshold: 0.5
- name: duplicate_row_check
max_duplicate_ratio: 0.1
semantic_engineOptional. When set, the solver routes through Cube or Looker instead of the bundled semantic layer.
semantic_engine:
vendor: cube # or `looker`
base_url: https://cube.example.com
api_token: "${CUBE_API_TOKEN}" # Cube only
# Looker variant
# semantic_engine:
# vendor: looker
# base_url: https://myco.looker.com
# client_id: "${LOOKER_CLIENT_ID}"
# client_secret: "${LOOKER_CLIENT_SECRET}"
${VAR} placeholders are resolved against the process environment at
startup. A missing variable fails fast — the solver never starts with an
empty credential.
A good instructions: string follows this shape:
instructions: |
You are a revenue analytics assistant for Acme Corp.
Conventions:
- All currency in USD; dates as ISO 8601.
- Fiscal quarter starts in February.
- "Customer" = the `customer` entity on the `accounts` topic, not
`users` (which counts seats).
Prefer measures defined in the semantic layer over hand-written
aggregations. If a question can be answered by the `revenue` topic,
do not author SQL.
Keep state-specific overrides surgical:
states:
clarifying:
instructions: |
"This week" means Monday 00:00 to Sunday 23:59 in America/New_York.
solving:
instructions: Always alias aggregate columns; prefer CTEs over subqueries.
Avoid duplicating the global instructions: inside per-state blocks —
they're concatenated, not replaced.
| Symptom / error | Likely cause | Fix |
|---|---|---|
no databases configured | databases: empty or missing | Add at least one connector name matching config.yml. |
unsupported connector type: … | databases: lists a name not in config.yml | Rename to match a real entry, or add the connector to config.yml. |
ambiguous table: … | Same table name in two configured databases | Either drop one database or qualify the topic's data_source to disambiguate. |
environment variable '${X}' is not set | ${VAR} placeholder in semantic_engine / llm | Export the env var before starting the server; missing values never silently pass through. |
unsupported semantic engine vendor: … | semantic_engine.vendor is not cube or looker | Use one of the two bundled adapters, or omit the section entirely. |
semantic engine connection error: … | semantic_engine.base_url unreachable / token rejected | Verify the URL and credentials with curl before launching the server. |
validation config error: unknown rule '…' | Rule name typo | Use only the rule names listed in the table above; case-sensitive snake_case. |
| State override silently ignored | Misspelled state key (solve vs solving) | State keys are fixed: clarifying, specifying, solving, executing, interpreting. |
thinking: false rejected | Boolean false is not a valid thinking mode | Use thinking: disabled (bare or quoted both work); the shorthand is a string identifier, never a boolean. |
LLM never sees the solving instructions | Question was answerable by the semantic layer | Move guidance into clarifying or interpreting; solving is skipped on the semantic path. |
YAML parse error: duplicate key | A top-level key (llm:, states:) appears twice | Each top-level key must appear at most once per file. |
.agentic.yml validation is structural — oxy validate parses the file
through the same loader the runtime uses but does not exercise the LLM.
# Parse a single file. Catches schema errors, missing env vars,
# unsupported vendors, glob errors.
oxy validate --file path/to/your.agentic.yml
# Parse every config in the project.
oxy validate
# Smoke-test the semantic layer (used in `solving` and `clarifying`).
# Run this before launching an agent against fresh views/topics.
oxy build
Iteration loop:
.agentic.yml.oxy validate --file <path> — catches structural errors fast.oxy build — catches semantic-layer drift the agent depends on.LlmStart/LlmEnd per round, ThinkingStart
bracketing reasoning, validator failures surfacing as Diagnosing
transitions. If a validator keeps tripping, tune its params under
validation: rather than disabling it outright.For features beyond this skill, query DeepWiki with:
I am a user of this project, not its maintainer. Please prioritize the project docs, examples, and json-schemas to answer my question: <…>
Restrict to the oxy-hq/oxy repository.
npx claudepluginhub oxy-hq/skills --plugin oxy-skillsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.