@oxy-hq/cli 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -8
- package/dist/main.mjs +4909 -3551
- package/dist/main.mjs.map +1 -1
- package/dist/{mcp-xxWL3_dz.mjs → mcp-Bdp0rX0l.mjs} +2 -2
- package/dist/{mcp-xxWL3_dz.mjs.map → mcp-Bdp0rX0l.mjs.map} +1 -1
- package/package.json +5 -5
- package/skills/oxy-agents/SKILL.md +318 -0
- package/skills/oxy-agents/references/quick-reference.md +222 -0
- package/skills/oxy-agents/templates/agentic-template.yml +141 -0
- package/skills/oxy-airway-pipelines/SKILL.md +223 -316
- package/skills/oxy-automations/SKILL.md +61 -15
- package/skills/oxy-cli/SKILL.md +37 -4
- package/skills/oxy-custom-apps/SKILL.md +193 -291
- package/skills/oxy-custom-apps/references/minimal-starter.md +63 -0
- package/skills/oxy-custom-apps/references/performance-and-usage.md +105 -0
- package/skills/oxy-custom-apps/references/reading-data.md +106 -0
- package/skills/oxy-custom-apps/references/sandbox-agent-loop.md +267 -0
- package/skills/oxy-custom-apps/references/verifying-in-the-browser.md +65 -0
- package/skills/oxy-data-apps/SKILL.md +362 -0
- package/skills/oxy-data-apps/references/examples.md +263 -0
- package/skills/oxy-data-apps/references/quick-reference.md +171 -0
- package/skills/oxy-data-apps/templates/dashboard-with-controls.app.yml +128 -0
- package/skills/oxy-data-apps/templates/simple-dashboard.app.yml +102 -0
- package/skills/oxy-data-architecture/SKILL.md +137 -152
- package/skills/oxy-evals/SKILL.md +362 -0
- package/skills/oxy-evals/references/diagnosis.md +243 -0
- package/skills/oxy-evals/references/results-json.md +145 -0
- package/skills/oxy-evals/references/writing-expected.md +112 -0
- package/skills/oxy-semantic-modeling/SKILL.md +239 -59
- package/skills/oxy-semantic-modeling/references/warehouse-casts.md +57 -0
- package/skills/oxy-semantic-modeling/templates/topic-template.yml +38 -0
- package/skills/oxy-semantic-modeling/templates/view-template.yml +119 -0
- package/template/.github/workflows/publish.yaml +15 -13
- package/template/.nvmrc +1 -1
- package/template/.oxyc-managed +5 -5
- package/template/README.md +21 -10
- package/template/package.json +3 -2
- package/template/pnpm-workspace.yaml +28 -17
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oxy-agents
|
|
3
|
+
description: >-
|
|
4
|
+
Use when creating, editing, reviewing or debugging an Oxy agent, a `.agentic.yml` file that
|
|
5
|
+
answers questions from the semantic model by clarifying, specifying, solving (SQL), executing
|
|
6
|
+
and interpreting. Triggers include "create an analytics agent", "my agent picks the wrong
|
|
7
|
+
metric", "my solving instructions are ignored", "the agent never uses my verified query", "the
|
|
8
|
+
agent can't see a database", "which tools can a state call", "set thinking, effort,
|
|
9
|
+
budget_tokens or extended thinking", "per-state model or max_retries", "validation rules",
|
|
10
|
+
"Cube or Looker semantic_engine", "analytics vs app-builder agent", "`.agent.yml` or
|
|
11
|
+
`.agentic.yml`", and validating, running (`oxy agentic run`) or testing (`oxy test`) an agent.
|
|
12
|
+
Not for writing the semantic model itself (views, topics) or automations.
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Oxy agents (`.agentic.yml`)
|
|
16
|
+
|
|
17
|
+
An Oxy agent is one YAML file, `<name>.agentic.yml`. It configures a fixed
|
|
18
|
+
pipeline that turns a natural-language question into a grounded query against
|
|
19
|
+
the semantic model, runs it, checks the result and explains it. You configure
|
|
20
|
+
the pipeline. You do not define its states or its tools.
|
|
21
|
+
|
|
22
|
+
## There is one kind of agent
|
|
23
|
+
|
|
24
|
+
- **`.agentic.yml` is the agent.** The classic `.agent.yml` format (a single
|
|
25
|
+
LLM call with custom tools) has been removed. Do not create one, and do not
|
|
26
|
+
copy one from an old workspace.
|
|
27
|
+
- **There is no `kind:` field.** Every `.agentic.yml` runs the same analytics
|
|
28
|
+
pipeline. A file named `app_builder.agentic.yml` is not special. Generating
|
|
29
|
+
`.app.yml` data apps, views or agent files is the in-product **Builder Agent**
|
|
30
|
+
(chat Build mode), and no `.agentic.yml` configures it.
|
|
31
|
+
- **Automations are a different file.** Deterministic multi-step work is an
|
|
32
|
+
automation, `.automation.yml` (`.procedure.yml` still works). `.workflow.yml`
|
|
33
|
+
is no longer recognised at all. An agent can *run* an automation it finds in
|
|
34
|
+
its context. It cannot *be* one.
|
|
35
|
+
- **Instruction-only agents skip the pipeline.** A file with `instructions:`
|
|
36
|
+
and no `databases:`, `context:` or `states:` is answered with one LLM call
|
|
37
|
+
and queries nothing. Add any of those three and you get the full pipeline.
|
|
38
|
+
|
|
39
|
+
**Use an agent** for conversational questions over data that has a semantic
|
|
40
|
+
model. **Use a verified query** (a `.sql` file with an `oxy:` header, below)
|
|
41
|
+
when one question must always get exactly the same SQL. **Use an automation**
|
|
42
|
+
when the steps are fixed and need no LLM to choose between them.
|
|
43
|
+
|
|
44
|
+
## Minimal file
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
llm:
|
|
48
|
+
ref: claude # a `name:` under config.yml `models:`
|
|
49
|
+
context:
|
|
50
|
+
- ./semantics/**/*.view.yml
|
|
51
|
+
- ./semantics/**/*.topic.yml
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That is enough when the views declare a `datasource`. The agent can query
|
|
55
|
+
every database its context references. The full annotated file is
|
|
56
|
+
[templates/agentic-template.yml](templates/agentic-template.yml).
|
|
57
|
+
|
|
58
|
+
Top-level keys: `instructions`, `timezone`, `databases`, `context`, `llm`,
|
|
59
|
+
`thinking`, `states`, `validation`, `semantic_engine`. All are optional.
|
|
60
|
+
**Unknown keys are ignored silently at every level**, by the runtime and by
|
|
61
|
+
both validators. A typo such as `stats:` or `solve:` costs you the setting
|
|
62
|
+
with no error.
|
|
63
|
+
|
|
64
|
+
## How a question flows
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
clarifying → specifying → solving → executing → interpreting → done
|
|
68
|
+
↑ ↑ ↑ ↑
|
|
69
|
+
└──────── diagnosing (when a check fails) ────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
1. **clarifying** classifies the question as a trend, comparison, breakdown,
|
|
73
|
+
single value, distribution, general inquiry, root cause or opportunity. It
|
|
74
|
+
searches the catalog and automations, and may ask the user to clarify.
|
|
75
|
+
Three outcomes leave the normal path early:
|
|
76
|
+
- **General inquiry** ("what metrics do you have?"). Answered directly,
|
|
77
|
+
with no query.
|
|
78
|
+
- **Root cause / opportunity** ("why did revenue drop?", "where can we
|
|
79
|
+
grow?"). Handled by metric-tree and anomaly tools, skipping
|
|
80
|
+
specifying/solving.
|
|
81
|
+
- **Confident semantic query.** If the model proposes the exact measures
|
|
82
|
+
and dimensions with high confidence and the semantic model compiles them,
|
|
83
|
+
specifying and solving are both skipped. Likewise when it selects a
|
|
84
|
+
verified query or automation, that is run instead.
|
|
85
|
+
2. **specifying** turns the question into a semantic query. If the semantic
|
|
86
|
+
model compiles it, **solving is skipped** and the compiled SQL runs.
|
|
87
|
+
3. **solving** writes SQL itself. This happens only when the semantic model
|
|
88
|
+
could not answer.
|
|
89
|
+
4. **executing** runs the SQL. It has no LLM. Then the result checks run.
|
|
90
|
+
5. **interpreting** writes the answer and picks a chart.
|
|
91
|
+
|
|
92
|
+
**Diagnosing** routes a failure back upstream:
|
|
93
|
+
|
|
94
|
+
- An unresolved metric or join, an empty result, a compile error or bad SQL
|
|
95
|
+
goes back to specifying.
|
|
96
|
+
- An ambiguous column goes back to clarifying.
|
|
97
|
+
- Outliers, a stale period or a bad chart go to interpreting, which still
|
|
98
|
+
answers and states the caveat.
|
|
99
|
+
|
|
100
|
+
The practical consequence: **guidance every answer needs goes in the global
|
|
101
|
+
`instructions:`, `clarifying` or `interpreting`, never only in `solving`.** On a
|
|
102
|
+
well-modelled workspace, solving rarely runs.
|
|
103
|
+
|
|
104
|
+
## Tools each state can call
|
|
105
|
+
|
|
106
|
+
The tool set is fixed by the runtime and is not configurable. There is no
|
|
107
|
+
`tools:` key.
|
|
108
|
+
|
|
109
|
+
| State | Tools |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| clarifying | `search_catalog`, `search_automations`, `propose_semantic_query`, `ask_user` |
|
|
112
|
+
| clarifying, root cause / opportunity | `explain_metric`, `find_opportunities`, `metric_sensitivity`, `predict_impact`, plus `list_anomalies`, `detect_anomalies` and `explain_anomaly` when anomaly monitoring is set up |
|
|
113
|
+
| specifying | `search_catalog`, `sample_columns`, `ask_user`. With a semantic model: `check_data_freshness`. Without one: `get_join_path`, `list_tables`, `describe_table` |
|
|
114
|
+
| solving | `execute_preview` (runs a candidate query with `LIMIT 5`) |
|
|
115
|
+
| executing | none |
|
|
116
|
+
| interpreting | `render_chart` |
|
|
117
|
+
|
|
118
|
+
`search_automations` searches only the automations and verified queries this
|
|
119
|
+
agent's `context:` reaches. With none, it finds nothing. The metric-tree and
|
|
120
|
+
anomaly tools are offered in interactive runs. They are not offered in
|
|
121
|
+
workspace previews or scheduled runs.
|
|
122
|
+
|
|
123
|
+
## The fields that matter
|
|
124
|
+
|
|
125
|
+
**`instructions`** go into every LLM state's system prompt. Use them for the
|
|
126
|
+
persona, business conventions ("fiscal year starts in February", "customer
|
|
127
|
+
means the `customers` view") and which views or topics to prefer. Per-state
|
|
128
|
+
`instructions` are **appended** to these, not substituted, so don't repeat the
|
|
129
|
+
global text in them.
|
|
130
|
+
|
|
131
|
+
**`timezone`** is an IANA name used for "today", "yesterday" and "last week".
|
|
132
|
+
It falls back to config.yml's `timezone:`, then UTC. An invalid name fails the
|
|
133
|
+
run.
|
|
134
|
+
|
|
135
|
+
**`databases`** lists names from config.yml `databases:`. The agent can query
|
|
136
|
+
exactly these plus every database its context files reference: a view's
|
|
137
|
+
`datasource` (or `data_source`), a verified query's `database:`, or an
|
|
138
|
+
automation task's `database:`. There is **no fallback to every database in
|
|
139
|
+
config.yml**. With none at all, the run fails with `no databases configured`.
|
|
140
|
+
|
|
141
|
+
**`context`** takes globs relative to the agent file's directory. Each match is
|
|
142
|
+
bucketed by its file name:
|
|
143
|
+
|
|
144
|
+
| Matches | Becomes |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| `*.view.yml`, `*.topic.yml` | the semantic catalog |
|
|
147
|
+
| `*.sql` with an `oxy:` header | a **verified query**: found by `search_automations` and run verbatim |
|
|
148
|
+
| `*.sql` without the header | SQL style examples in the solving prompt only |
|
|
149
|
+
| `*.md` | domain notes in the clarifying and interpreting prompts |
|
|
150
|
+
| `*.automation.yml`, `*.procedure.yml` | automations the agent may pick and run |
|
|
151
|
+
| anything else | ignored |
|
|
152
|
+
|
|
153
|
+
A verified query opts in with a leading comment block:
|
|
154
|
+
|
|
155
|
+
```sql
|
|
156
|
+
/*
|
|
157
|
+
oxy:
|
|
158
|
+
description: Monthly revenue by region
|
|
159
|
+
database: warehouse
|
|
160
|
+
*/
|
|
161
|
+
SELECT ...
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Without the header, the same file is only a style hint. Context files under a
|
|
165
|
+
dot-directory, `build/`, `dist/`, `target/` or `node_modules/`, or with
|
|
166
|
+
`.test.` in the name, are not deployed, so a glob that works on your machine
|
|
167
|
+
can come back empty in the cloud.
|
|
168
|
+
|
|
169
|
+
**`llm`** picks the model.
|
|
170
|
+
|
|
171
|
+
- `ref` names a model in config.yml `models:`, and the vendor, API key and base
|
|
172
|
+
URL come from that entry. In the cloud the key is a workspace secret, so
|
|
173
|
+
prefer `ref`.
|
|
174
|
+
- With neither `ref` nor `model`, the first model in config.yml is used.
|
|
175
|
+
- `model` overrides only the model ID. On its own (no `ref`) it uses
|
|
176
|
+
`api_key` or the server's `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`.
|
|
177
|
+
- `vendor` (`anthropic`, `open_ai`, `open_ai_compat`) overrides the ref's wire
|
|
178
|
+
protocol. Use `open_ai_compat` for gateways that serve only
|
|
179
|
+
`/chat/completions`.
|
|
180
|
+
- Google/Gemini models are not supported in agents.
|
|
181
|
+
|
|
182
|
+
**`states`** honours four keys: `clarifying`, `specifying`, `solving` and
|
|
183
|
+
`interpreting`.
|
|
184
|
+
|
|
185
|
+
- `executing` has no LLM, so it is accepted and does nothing. Every other key
|
|
186
|
+
is ignored.
|
|
187
|
+
- Each state takes `instructions`, `thinking`, `model` and `max_retries`.
|
|
188
|
+
- `model` is a provider model ID. It inherits the vendor, key and base URL
|
|
189
|
+
from `llm:`, so it must be the same provider.
|
|
190
|
+
- `max_retries` is the number of **tool-call rounds** per visit. When they run
|
|
191
|
+
out, the run pauses and asks the user whether to continue. It is not a
|
|
192
|
+
failure-retry count. Defaults: specifying 5, solving 3, interpreting 5.
|
|
193
|
+
Clarifying has a fixed limit and ignores the setting.
|
|
194
|
+
|
|
195
|
+
**`validation`** sets the result checks. Leave it out and 15 default checks
|
|
196
|
+
run. If you include it, it **replaces** the defaults: only the rules you list
|
|
197
|
+
run, and a stage you leave empty is not checked. To switch one check off or
|
|
198
|
+
retune it, list every rule that should still run. Rule names and parameters
|
|
199
|
+
are in [references/quick-reference.md](references/quick-reference.md).
|
|
200
|
+
|
|
201
|
+
**`semantic_engine`** routes queries through Cube or Looker ahead of Oxy's own
|
|
202
|
+
semantic model. `${VAR}` placeholders are read from the server's environment,
|
|
203
|
+
not from workspace secrets. The engine is pinged when a run starts, and an
|
|
204
|
+
unreachable engine fails the run.
|
|
205
|
+
|
|
206
|
+
## Thinking and models
|
|
207
|
+
|
|
208
|
+
Thinking is resolved per state, in this order:
|
|
209
|
+
|
|
210
|
+
1. the state's own `thinking`
|
|
211
|
+
2. `llm.thinking`
|
|
212
|
+
3. top-level `thinking`
|
|
213
|
+
4. the state's built-in default: **adaptive for solving, disabled for
|
|
214
|
+
everything else**
|
|
215
|
+
|
|
216
|
+
A global value replaces every built-in default. So top-level
|
|
217
|
+
`thinking: adaptive` makes clarifying, specifying and interpreting think too,
|
|
218
|
+
and `llm.thinking: disabled` turns thinking off in solving. Prefer per-state
|
|
219
|
+
settings.
|
|
220
|
+
|
|
221
|
+
| Form | Meaning |
|
|
222
|
+
| --- | --- |
|
|
223
|
+
| `adaptive` | the model decides when and how much to think |
|
|
224
|
+
| `disabled` | no thinking (bare or quoted; **never** `false`, which is a parse error) |
|
|
225
|
+
| `effort:high` or `{effort: high}` | depth hint: `low`, `medium`, `high`, `xhigh`, `max` |
|
|
226
|
+
| `{budget_tokens: 10000}` | hard token ceiling (Claude 4.6 and earlier) |
|
|
227
|
+
|
|
228
|
+
How each provider treats these forms:
|
|
229
|
+
|
|
230
|
+
- **Anthropic.** `adaptive` and `effort` are native from Claude 4.6, and
|
|
231
|
+
`xhigh` from 4.7. Claude 4.7 and later **reject** `budget_tokens`, so Oxy
|
|
232
|
+
sends it as the nearest effort level and logs a warning. On older models it
|
|
233
|
+
goes the other way: `adaptive` and `effort` become a token budget, and
|
|
234
|
+
`xhigh` becomes `high`. Write `effort` on current models.
|
|
235
|
+
- **OpenAI** (`open_ai`, Responses API). `effort` maps to reasoning effort,
|
|
236
|
+
with `xhigh` and `max` sent as `high`. `adaptive` leaves the model's default
|
|
237
|
+
effort. `budget_tokens` is ignored.
|
|
238
|
+
- **`open_ai_compat`.** Any setting other than `disabled` adds a
|
|
239
|
+
chain-of-thought instruction to the prompt, because there is no native
|
|
240
|
+
control.
|
|
241
|
+
|
|
242
|
+
A string that isn't one of the forms above (`thinking: enabled`,
|
|
243
|
+
`thinking: high`) silently means **disabled**. An unknown effort level
|
|
244
|
+
silently means `medium`.
|
|
245
|
+
|
|
246
|
+
`llm.extended_thinking: {model, thinking}` is used while the user has the
|
|
247
|
+
**extended thinking** toggle on (`--thinking-mode extended_thinking` from the
|
|
248
|
+
CLI). It replaces the model and the thinking setting in every state. Without
|
|
249
|
+
the block, the toggle changes nothing.
|
|
250
|
+
|
|
251
|
+
Leave `llm.max_tokens` unset unless you need a hard cap. When it is unset, Oxy
|
|
252
|
+
uses 4,096 without thinking and 16,384 (or the budget plus 4,096) with
|
|
253
|
+
thinking. A value you set is used as-is, and thinking tokens count against it.
|
|
254
|
+
|
|
255
|
+
## Validate, run, test
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
oxyc validate --file agents/sales.agentic.yml # offline schema check, no server
|
|
259
|
+
oxy validate --file agents/sales.agentic.yml # the runtime's own parser
|
|
260
|
+
oxy agentic run agents/sales.agentic.yml -q "Revenue by region last quarter?"
|
|
261
|
+
oxy test agents/sales.agentic.test.yml # LLM-judged evals
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
- **Both validators are structural only.** They catch a bad shape (a
|
|
265
|
+
malformed `thinking`, a wrong type, a duplicate key). `oxyc validate` also
|
|
266
|
+
rejects the vendor spellings `openai` and `openai_compat`, which the runtime
|
|
267
|
+
accepts, so write `open_ai` and `open_ai_compat` to satisfy both. Neither
|
|
268
|
+
validator resolves `databases:` or `llm.ref`, expands globs, reads `${VAR}`
|
|
269
|
+
placeholders, checks rule names or timezones, or notices unknown keys.
|
|
270
|
+
- **The first full check is a run.** `oxy agentic run <path> -q "<question>"`
|
|
271
|
+
builds the agent exactly as the server does and streams each state. It runs
|
|
272
|
+
in a workspace directory and needs Oxy's Postgres database (`OXY_DATABASE_URL`),
|
|
273
|
+
like `oxy serve`. Add `--json` for JSONL events, or `--thinking-mode
|
|
274
|
+
extended_thinking`. A CLI run that pauses to ask the user something can't be
|
|
275
|
+
usefully resumed from the CLI, because `oxy agentic answer` only marks the
|
|
276
|
+
run as running and does not deliver the text. Ask a more specific question,
|
|
277
|
+
or continue in the app.
|
|
278
|
+
- **`oxy build` does not check agents.** It builds search embeddings and syncs
|
|
279
|
+
integrations.
|
|
280
|
+
- **`oxy test`** runs `.test.yml` evals against an agent and scores each case
|
|
281
|
+
with an LLM judge. The format and flags are in
|
|
282
|
+
[references/quick-reference.md](references/quick-reference.md).
|
|
283
|
+
|
|
284
|
+
To point an editor at the schema, start the file with:
|
|
285
|
+
|
|
286
|
+
```yaml
|
|
287
|
+
# yaml-language-server: $schema=https://raw.githubusercontent.com/oxy-hq/oxygen/refs/heads/main/json-schemas/agentic.json
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Pitfalls
|
|
291
|
+
|
|
292
|
+
| Symptom | Cause | Fix |
|
|
293
|
+
| --- | --- | --- |
|
|
294
|
+
| `no databases configured` | nothing in `databases:` and no context file references a database | add a name from config.yml, or views with `datasource` |
|
|
295
|
+
| agent can't see a table it "should" | the agent only reaches databases it declares or references | add it to `databases:` |
|
|
296
|
+
| wrong model answers, or an auth error on the first question | `llm.ref` is not a `name:` in config.yml, so the agent fell back to a built-in Claude model and the server's `ANTHROPIC_API_KEY`; or the model's key secret is unset | fix the name; set the key |
|
|
297
|
+
| "does not have a metric tree configured" | the question was classified as root cause or opportunity, and this workspace or run has no metric tree | define a metric tree, or ask for the numbers directly |
|
|
298
|
+
| `solving` instructions never take effect | the semantic model compiled the question, so solving was skipped | move them to the global `instructions:` or `clarifying` |
|
|
299
|
+
| verified query never chosen | `.sql` has no `oxy:` header, or isn't matched by `context:` | add the header and a `description`; check the glob |
|
|
300
|
+
| state override does nothing | misspelled key, or `executing` / `clarifying.max_retries` | use the four honoured keys |
|
|
301
|
+
| thinking silently off | `thinking: enabled` or another unknown string | use one of the forms above |
|
|
302
|
+
| `thinking: false` rejected | boolean, not a mode | `thinking: disabled` |
|
|
303
|
+
| a default check stopped running | a `validation:` section replaced the defaults | list every rule you still want |
|
|
304
|
+
| `validation config error: unknown … rule` | rule name typo, or a rule under the wrong stage | names and stages are in the quick reference |
|
|
305
|
+
| `invalid timezone '…'` | not an IANA name | e.g. `America/New_York`, `UTC` |
|
|
306
|
+
| `environment variable '${X}' … is not set` | `semantic_engine` placeholder unset on the server | set it in the server environment |
|
|
307
|
+
| `semantic engine connection error` | Cube/Looker unreachable or rejected the credentials | check `base_url` and credentials |
|
|
308
|
+
| agent missing in the cloud, fine locally | `.agentic.yaml` extension, a dot-directory/`build/` path, or `.test.` in the name | rename or move it |
|
|
309
|
+
|
|
310
|
+
## Read next
|
|
311
|
+
|
|
312
|
+
- [references/quick-reference.md](references/quick-reference.md): every field,
|
|
313
|
+
default, rule and parameter in tables, plus the `.test.yml` format.
|
|
314
|
+
- [templates/agentic-template.yml](templates/agentic-template.yml): an annotated
|
|
315
|
+
starter file that validates against the schema.
|
|
316
|
+
- Related skills: **oxy-semantic-modeling** for the views and topics an agent
|
|
317
|
+
queries, **oxy-evals** for writing and repairing `.test.yml` evals, and
|
|
318
|
+
**oxy-automations** for automations.
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# `.agentic.yml` quick reference
|
|
2
|
+
|
|
3
|
+
Dense tables. The reasoning behind them is in [../SKILL.md](../SKILL.md); a
|
|
4
|
+
starter file is [../templates/agentic-template.yml](../templates/agentic-template.yml).
|
|
5
|
+
|
|
6
|
+
## File
|
|
7
|
+
|
|
8
|
+
| Rule | Detail |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| Name | `<name>.agentic.yml`. `.agentic.yaml` is not deployed to the cloud |
|
|
11
|
+
| Location | anywhere in the workspace, except under a dot-directory, `build/`, `dist/`, `target/` or `node_modules/` |
|
|
12
|
+
| Not deployed | any file with `.test.` in its name (that is the eval-file convention) |
|
|
13
|
+
| Referenced as | its workspace-relative path, e.g. `agents/sales.agentic.yml`. The UI shows the stem (`sales`) |
|
|
14
|
+
| Unknown keys | ignored silently at every level, by the runtime and by both validators |
|
|
15
|
+
| Duplicate keys | a YAML parse error |
|
|
16
|
+
| Editor schema | `# yaml-language-server: $schema=https://raw.githubusercontent.com/oxy-hq/oxygen/refs/heads/main/json-schemas/agentic.json` |
|
|
17
|
+
|
|
18
|
+
## Top-level fields
|
|
19
|
+
|
|
20
|
+
| Field | Type | Default | Notes |
|
|
21
|
+
| --- | --- | --- | --- |
|
|
22
|
+
| `instructions` | string | none | Added to every LLM state's system prompt |
|
|
23
|
+
| `timezone` | IANA name | config.yml `timezone:`, then UTC | Used for "today" and relative dates. An invalid name fails the run |
|
|
24
|
+
| `databases` | list of config.yml database names | `[]` | Combined with the databases the context references. There is no all-databases fallback |
|
|
25
|
+
| `context` | list of globs | `[]` | Relative to the agent file's directory |
|
|
26
|
+
| `llm` | map | see below | Model, key, thinking |
|
|
27
|
+
| `thinking` | thinking form | none | Global thinking. Overrides each state's built-in default; `llm.thinking` overrides it |
|
|
28
|
+
| `states` | map | `{}` | Per-state overrides |
|
|
29
|
+
| `validation` | map | 15 default rules | **Replaces** the defaults when present |
|
|
30
|
+
| `semantic_engine` | map | none | Cube or Looker ahead of Oxy's semantic model |
|
|
31
|
+
|
|
32
|
+
An instruction-only agent (`instructions`, and no `databases`, `context` or
|
|
33
|
+
`states`) is one LLM call. It runs no pipeline and no queries.
|
|
34
|
+
|
|
35
|
+
## `llm:`
|
|
36
|
+
|
|
37
|
+
| Field | Default | Notes |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| `ref` | none | A `name:` under config.yml `models:`. Supplies the vendor, key (a workspace secret in the cloud), base URL, Azure settings and headers |
|
|
40
|
+
| `model` | from `ref`, else the first config.yml model | A provider model ID. Setting `model` without `ref` skips config.yml entirely, so the key must come from `api_key` or the server environment |
|
|
41
|
+
| `vendor` | from `ref`, else `anthropic` | `anthropic`, `open_ai` (Responses API) or `open_ai_compat` (`/chat/completions`). The runtime also accepts `openai` and `openai_compat`; `oxyc validate` does not |
|
|
42
|
+
| `api_key` | from `ref`, else `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` on the server | Prefer `ref` |
|
|
43
|
+
| `base_url` | from `ref`, else the provider default | `open_ai_compat` defaults to `http://localhost:11434/v1` |
|
|
44
|
+
| `max_tokens` | 4,096 without thinking; 16,384 (or budget + 4,096) with thinking | A value you set is used as-is, and thinking tokens count against it |
|
|
45
|
+
| `thinking` | none | Beats top-level `thinking` |
|
|
46
|
+
| `extended_thinking` | none | `{model, thinking}`. Replaces both in every state while the user's extended-thinking toggle is on |
|
|
47
|
+
|
|
48
|
+
A `ref` that is not in config.yml is not an error at load time. The agent falls
|
|
49
|
+
back to a built-in Claude model and the server's `ANTHROPIC_API_KEY`.
|
|
50
|
+
Google/Gemini models are not supported in agents.
|
|
51
|
+
|
|
52
|
+
## `states:`
|
|
53
|
+
|
|
54
|
+
| Key | LLM | Thinking default | `max_retries` default | Prompt extras |
|
|
55
|
+
| --- | --- | --- | --- | --- |
|
|
56
|
+
| `clarifying` | yes | disabled | fixed; the setting is ignored | `.md` context docs |
|
|
57
|
+
| `specifying` | yes | disabled | 5 | SQL dialect |
|
|
58
|
+
| `solving` | yes | adaptive | 3 | SQL dialect, `.sql` examples |
|
|
59
|
+
| `executing` | **no** | n/a | n/a | key accepted, does nothing |
|
|
60
|
+
| `interpreting` | yes | disabled | 5 | `.md` context docs |
|
|
61
|
+
|
|
62
|
+
Any other key (`solve`, `diagnosing`, …) is ignored silently.
|
|
63
|
+
|
|
64
|
+
| Per-state field | Notes |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `instructions` | **Appended** after the global `instructions` for this state |
|
|
67
|
+
| `thinking` | Any thinking form. Highest precedence (except the extended-thinking toggle) |
|
|
68
|
+
| `model` | Provider model ID. Inherits the vendor, key and base URL from `llm:`, so it must be the same provider |
|
|
69
|
+
| `max_retries` | Tool-call rounds per visit. When they run out, the run pauses and asks the user whether to continue |
|
|
70
|
+
|
|
71
|
+
## Thinking
|
|
72
|
+
|
|
73
|
+
| Form | Meaning |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `adaptive` | the model decides |
|
|
76
|
+
| `disabled` / `"disabled"` | off |
|
|
77
|
+
| `effort:<level>` / `{effort: <level>}` | `low`, `medium`, `high`, `xhigh`, `max`. An unknown level means `medium` |
|
|
78
|
+
| `{budget_tokens: N}` | hard ceiling. Native on Claude 3.7 to 4.6 |
|
|
79
|
+
| any other string | silently **disabled** |
|
|
80
|
+
| `false` / `true` | parse error |
|
|
81
|
+
|
|
82
|
+
Precedence, highest first: the extended-thinking toggle, then `states.<s>.thinking`,
|
|
83
|
+
then `llm.thinking`, then top-level `thinking`, then the state default.
|
|
84
|
+
|
|
85
|
+
| Provider | `adaptive` | `effort` | `budget_tokens` |
|
|
86
|
+
| --- | --- | --- | --- |
|
|
87
|
+
| Anthropic, Claude 4.7+ | native | native, all 5 levels | API rejects it; Oxy sends the nearest effort level and warns |
|
|
88
|
+
| Anthropic, Claude 4.6 | native | native; `xhigh` → `high` | native |
|
|
89
|
+
| Anthropic, 3.7 to 4.5 | sent as a mid-range budget | sent as a budget; `xhigh` → `high` | native |
|
|
90
|
+
| OpenAI (`open_ai`) | the model's default reasoning | reasoning effort; `xhigh` and `max` → `high` | ignored |
|
|
91
|
+
| `open_ai_compat` | chain-of-thought prompt | chain-of-thought prompt | chain-of-thought prompt |
|
|
92
|
+
|
|
93
|
+
## `context:` buckets
|
|
94
|
+
|
|
95
|
+
| Matches | Becomes | Also |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| `*.view.yml`, `*.view.yaml` | semantic catalog | its `datasource` / `data_source` adds a database |
|
|
98
|
+
| `*.topic.yml`, `*.topic.yaml` | semantic catalog | |
|
|
99
|
+
| `*.sql` with an `oxy:` header | verified query, run verbatim when chosen | header `database:` adds a database |
|
|
100
|
+
| `*.sql` without the header | SQL examples in the solving prompt | |
|
|
101
|
+
| `*.md` | domain notes for clarifying and interpreting | |
|
|
102
|
+
| `*.automation.yml/.yaml`, `*.procedure.yml/.yaml` | automations `search_automations` can return | task `database:` values add databases |
|
|
103
|
+
| anything else | ignored | |
|
|
104
|
+
|
|
105
|
+
Verified-query header fields: `description` (used to match the question) and
|
|
106
|
+
`database` (the connection to run on).
|
|
107
|
+
|
|
108
|
+
```sql
|
|
109
|
+
/*
|
|
110
|
+
oxy:
|
|
111
|
+
description: Weekly sales for all stores
|
|
112
|
+
database: warehouse
|
|
113
|
+
*/
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Tools by state (fixed; no `tools:` key)
|
|
117
|
+
|
|
118
|
+
| State | Tools |
|
|
119
|
+
| --- | --- |
|
|
120
|
+
| clarifying | `search_catalog`, `search_automations`, `propose_semantic_query`, `ask_user` |
|
|
121
|
+
| clarifying → root cause / opportunity | `explain_metric`, `find_opportunities`, `metric_sensitivity`, `predict_impact`, `search_catalog`, `search_automations`, `propose_semantic_query`; with anomaly monitoring also `list_anomalies`, `detect_anomalies`, `explain_anomaly` |
|
|
122
|
+
| specifying | `search_catalog`, `sample_columns`, `ask_user`; with a semantic model `check_data_freshness`; without one `get_join_path`, `list_tables`, `describe_table` |
|
|
123
|
+
| solving | `execute_preview` |
|
|
124
|
+
| executing | none |
|
|
125
|
+
| interpreting | `render_chart` |
|
|
126
|
+
|
|
127
|
+
Root-cause and opportunity questions need a metric tree. Without one the agent
|
|
128
|
+
replies that the workspace "does not have a metric tree configured". Metric-tree
|
|
129
|
+
and anomaly tools are not offered in workspace previews or scheduled runs.
|
|
130
|
+
|
|
131
|
+
## `validation:`
|
|
132
|
+
|
|
133
|
+
Absent: the 15 rules marked default run. Present: only the listed rules run (an
|
|
134
|
+
entry with `enabled: false` is skipped), and a stage with no list is not
|
|
135
|
+
checked. Entry shape: `- name: <rule>`, optional `enabled`, plus the rule's
|
|
136
|
+
parameters at the same level. Misspelled parameters are ignored silently.
|
|
137
|
+
|
|
138
|
+
| Stage (checked after) | Rule | Default | Params (default) | Fails when |
|
|
139
|
+
| --- | --- | --- | --- | --- |
|
|
140
|
+
| `specified` (specifying) | `metric_resolves` | yes | | a resolved metric's table or column is not in the catalog |
|
|
141
|
+
| | `join_key_exists` | yes | | a join's tables or key are not in the catalog |
|
|
142
|
+
| | `filter_unambiguous` | yes | | a filter column is unknown or matches several tables |
|
|
143
|
+
| `solvable` (solving) | `sql_syntax` | yes | `dialect` (`generic`): accepted, but parsing is generic whatever its value | the SQL does not parse |
|
|
144
|
+
| | `tables_exist_in_catalog` | yes | | `FROM`/`JOIN` names a table the catalog lacks |
|
|
145
|
+
| | `spec_tables_present` | yes | | a table the spec resolved is missing from the SQL |
|
|
146
|
+
| | `column_refs_valid` | yes | | a `table.column` reference does not exist |
|
|
147
|
+
| | `timeseries_order_by_check` | yes | | a time series has no outer `ORDER BY` |
|
|
148
|
+
| `solved` (executing) | `non_empty` | yes | | zero rows |
|
|
149
|
+
| | `truncation_warning` | yes | | a scalar or series result hit the row cap |
|
|
150
|
+
| | `no_nan_inf` | yes | | NaN or ±∞ in a numeric cell |
|
|
151
|
+
| | `outlier_detection` | yes | `threshold_sigma` (5.0), `min_rows` (4) | a value is beyond the z-score threshold |
|
|
152
|
+
| | `null_ratio_check` | yes | `threshold` (0.5) | a numeric column's NULL share is above the threshold |
|
|
153
|
+
| | `duplicate_row_check` | yes | `max_duplicate_ratio` (0.1) | the duplicate-row share is above the ratio |
|
|
154
|
+
| | `freshness_check` | yes | `threshold_days` (1) | the requested range runs past the latest date in the result |
|
|
155
|
+
| | `shape_match` | no | | the result doesn't have the expected shape |
|
|
156
|
+
| | `timeseries_date_check` | no | | a time series' first column is not date-like |
|
|
157
|
+
|
|
158
|
+
Where a failure goes (diagnosing):
|
|
159
|
+
|
|
160
|
+
| Failure | Back to |
|
|
161
|
+
| --- | --- |
|
|
162
|
+
| unresolved metric or join, empty result, semantic compile error | specifying |
|
|
163
|
+
| SQL syntax, null ratio or duplicates found after solving | specifying (fresh attempt) |
|
|
164
|
+
| ambiguous column | clarifying |
|
|
165
|
+
| outlier, freshness gap, bad chart config | interpreting (answers and states the caveat) |
|
|
166
|
+
|
|
167
|
+
## `semantic_engine:`
|
|
168
|
+
|
|
169
|
+
| Field | Cube | Looker |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| `vendor` | `cube` | `looker` |
|
|
172
|
+
| `base_url` | required | required |
|
|
173
|
+
| `api_token` | used | n/a |
|
|
174
|
+
| `client_id`, `client_secret` | n/a | used |
|
|
175
|
+
|
|
176
|
+
`${VAR}` is read from the **server's environment**. If the variable is unset,
|
|
177
|
+
or the engine is unreachable at run start, the run fails.
|
|
178
|
+
|
|
179
|
+
## Commands
|
|
180
|
+
|
|
181
|
+
| Command | Checks |
|
|
182
|
+
| --- | --- |
|
|
183
|
+
| `oxyc validate --file <path>` | JSON-schema shape, offline. Catches wrong types, a malformed `thinking` and vendor spelling. Misses unknown keys, `ref`, databases, globs, rule names, env vars |
|
|
184
|
+
| `oxy validate --file <path>` | parses with the runtime's own parser. Structural only, with the same blind spots |
|
|
185
|
+
| `oxy agentic run <path> -q "<question>"` | the real build and run, streamed by state. `--json`, `--thinking-mode extended_thinking`. Needs Oxy's Postgres (`OXY_DATABASE_URL`) |
|
|
186
|
+
| `oxy test [<file>.test.yml]` | LLM-judged evals; with no file, every `*.test.yml` in the workspace |
|
|
187
|
+
| `oxy build` | not an agent check: it builds embeddings and syncs integrations |
|
|
188
|
+
|
|
189
|
+
## `.test.yml` (evals)
|
|
190
|
+
|
|
191
|
+
```yaml
|
|
192
|
+
target: agents/sales.agentic.yml # workspace-relative; omit to infer it
|
|
193
|
+
settings:
|
|
194
|
+
runs: 3 # runs per case (default 3), used for consistency
|
|
195
|
+
concurrency: 5 # default 5
|
|
196
|
+
judge_model: gpt-5-mini # config.yml model name; use a different family
|
|
197
|
+
cases:
|
|
198
|
+
- name: weekly-total # optional
|
|
199
|
+
prompt: "What were total sales last week?"
|
|
200
|
+
expected: "Total sales were $1.2M"
|
|
201
|
+
tags: [sales, critical]
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Detail | Value |
|
|
205
|
+
| --- | --- |
|
|
206
|
+
| Target inference | `sales.agentic.test.yml` tests `sales.agentic.yml` in the same directory |
|
|
207
|
+
| Target kind | must be an `.agentic.yml` |
|
|
208
|
+
| `tool:` on a case | parsed, not yet checked |
|
|
209
|
+
| Useful flags | `--tag <t>`, `--case <index-or-name>`, `--min-accuracy 0.8` (exit 1 below), `--threshold-mode average\|all`, `--format json`, `--output-json`, `-v` |
|
|
210
|
+
|
|
211
|
+
## Errors → fix
|
|
212
|
+
|
|
213
|
+
| Message | Fix |
|
|
214
|
+
| --- | --- |
|
|
215
|
+
| `no databases configured` | name a database in `databases:`, or give context views a `datasource` |
|
|
216
|
+
| `YAML parse error: …` | malformed YAML, a duplicate key, `thinking: false`, or an unknown `semantic_engine.vendor` |
|
|
217
|
+
| `validation config error: unknown <stage> rule: '…'` | fix the rule name or move it to its stage |
|
|
218
|
+
| `validation config error: invalid params for rule '…'` | fix the parameter's type |
|
|
219
|
+
| `invalid timezone '…'` | use an IANA name |
|
|
220
|
+
| `environment variable '${X}' referenced in config is not set` | set it in the server environment |
|
|
221
|
+
| `semantic engine connection error: …` | check `base_url` and credentials |
|
|
222
|
+
| `glob pattern error: …` | fix the `context:` pattern |
|