Vibe coding with AI agents¶
"Vibe coding" here means using an AI coding agent (Claude Code, Cursor, Aider, GitHub Copilot, …) to author workflows in athena-sdk-lite by describing what you want in natural language, then letting the agent generate the Python.
This only works if the agent knows the SDK's conventions: the canonical import pattern, the 11 helpers and their kwargs, how branch conditions are written, what transform code looks like, what NOT to do. That's what AGENTS.md is — a context file the agent reads first, every time, so it doesn't have to guess.
The pattern in 3 steps¶
1. Point your agent at AGENTS.md¶
| Agent | How |
|---|---|
| Claude Code | Auto-discovers AGENTS.md at the repo root. No setup. |
| Cursor | Auto-discovers AGENTS.md (also reads .cursor/rules/*.mdc). |
| Aider | aider --read AGENTS.md |
| Copilot | Add AGENTS.md to the chat context, or paste the relevant section before each prompt. |
| Anything else | Open AGENTS.md, copy contents, paste as the first system/user message. |
The file lives at the repo root (athena-sdk-lite/AGENTS.md) because that's where coding agents look by convention. The same content is mirrored at docs/AGENTS.md so MkDocs can serve it; keep the two in sync if you edit.
2. Describe the workflow you want¶
Plain English, focused on business intent, not Python syntax:
Build a workflow that pulls active orders from Postgres, flags high-value ones (>$1000) using a custom transform, sends them to our fraud-detection agent, branches on fraud_score > 0.7, and writes alerts and the routine queue into two different output sinks.
A well-briefed agent reading AGENTS.md will produce something close to the worked example in Building a workflow on the first try.
3. Validate before you trust¶
An agent can write code that parses but doesn't validate (missing upstream, broken branch wiring, unsupported kwarg). The validator catches these structurally before you run anything. Add it to your pre-commit hook so generated workflows can't sneak into main.
What's in AGENTS.md¶
The file is structured for fast LLM scanning, not human reading. It covers:
- The single canonical import pattern (function-first, never method-first for new code)
- All 11 helpers with required kwargs and a one-line "notes" column
- How to wire nodes (
inputs=, fan-out, fan-in, branch ports) - Branch condition syntax (
$input.data.get(...)) transformcode shape (inputs["data"]row stream, return same shape)- Variables and
{{ name }}templating - Anti-patterns the agent must NOT generate (no internal URLs, no inlined creds, no
_engine.*imports, no mixing styles) - File layout convention (
workflows/<name>.py)
Open AGENTS.md to read the current version.
A sample prompt¶
Once your agent has the AGENTS.md context, prompts can be short and intent-focused:
Build me a workflow
workflows/adverse_event_triage.pythat:
- Pulls the last 24 hours of
adverse_eventsfrom Postgres wheretriage_status IS NULL- Runs custom Python to compute
days_since_onsetand flag rows wherenarrativecontains any of {death, hospitalized, anaphylaxis, seizure, stroke}- Sends each row to the AE-classification agent at
{{ agent_url }}and gets back a severity classification- Branches: if classification is in (serious, life_threatening) OR rows have missing critical fields → build an SAE alert payload and insert into
sae_escalations; otherwise → minimal projection inserted intotriage_queueUse the variables
agent_urlanddb_password(already set externally). Do not hardcode any URLs.
The agent should produce something equivalent to examples/11_triage_pipeline.py.
Reviewing what the agent wrote¶
Things to check before accepting agent-generated code:
| Check | How |
|---|---|
Imports from athena_sdk_lite.nodes |
Top of file uses from athena_sdk_lite.nodes import ... |
Body wrapped in with Workflow(...) as wf: |
Single with block, no module-level wf = Workflow(...) |
| No real internal hostnames or credentials | grep for aviradigital, aviralabs, internal, passwords |
Branch conditions use $input.data.get(...) |
Not raw Python; not row["key"] direct access |
Transforms return {"data": [...]} |
Same shape they receive; not a bare list |
wf.validate() returns [] |
Run the file; check the printed validation result |
| Validates in a subprocess (clean state) | python workflows/your_file.py exits 0 |
If you have tests/test_examples_validate.py-style infrastructure, drop the generated file into workflows/ and let CI run it.
Things AGENTS.md will NOT fix¶
The agent still hallucinates occasionally. Common failure modes:
- Inventing a helper that doesn't exist. The 11 helpers in AGENTS.md are the full set (plus the
wf.add_nodeescape hatch). If the agent writeswf.snowflake(...), it's wrong. - Mixing method-first and function-first. AGENTS.md forbids this for new code, but agents sometimes regress to method-first. Look for
wf.pubmed(...)etc. and rewrite. - Hallucinating engine node types in
wf.add_node. The valid types are whatever the vendored engine supports; checksrc/athena_sdk_lite/_engine/if a generatedtype=looks suspicious. - Inventing branch condition syntax. The valid form is
$input.data.<expr>. Anything else (e.g.row.score > 0.8) is wrong.
When you spot a recurring failure mode, add an explicit "do not" line to AGENTS.md and the agent will stop doing it next time.
CI gate for vibe-coded workflows¶
If you're letting agents author workflows on a regular basis, make this a pre-commit hook:
# .git/hooks/pre-commit (or use pre-commit framework)
python -c "
import sys, importlib.util
from pathlib import Path
failed = []
for f in Path('workflows').glob('*.py'):
spec = importlib.util.spec_from_file_location(f.stem, f)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
if hasattr(mod, 'wf'):
issues = mod.wf.validate()
if issues:
failed.append((str(f), issues))
if failed:
for f, issues in failed:
print(f'❌ {f}: {issues}')
sys.exit(1)
print('✅ all workflows validate')
"
If a generated workflow doesn't validate, the commit is rejected. Cheap, prevents drift, gives you confidence that agent-authored code didn't sneak structural bugs into your repo.
Next¶
- AGENTS.md → — the context file itself
- Building a workflow → — to internalize what good output looks like
- How nodes connect → — to spot wiring mistakes