Llm app code
Skill pipipip169/fable5-handoff/sources/adamentwistle-fable-skills/llm-app-code
Code calling LLM APIs — model output is untrusted input: defensive parsing, server-side schema validation, authorization never from model output, approval-gated writes, injection awareness, cache-prefix economics, streaming edges. Use for agent loops, tool definitions, or prompt/model changes.From its SKILL.md
npx -y skills add pipipip169/fable5-handoff --skill llm-app-codeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.8 KB, 741 tokens by cl100k_base, as published. Nobody here has run it
LLM App Code
Code around an LLM has one governing fact: the model is an untrusted, non-deterministic input source that reads like a trusted colleague. Most LLM-app bugs come from forgetting one half of that sentence.
Model output is untrusted input — always
- Parse defensively. Every
JSON.parseof model output wrapped and shape-validated; expect markdown fences around JSON, trailing prose, truncated output at max_tokens, and empty strings. A malformed model response must degrade a turn, never crash the app. - Validate tool-call arguments against the schema server-side before execution — required keys, types, enums, AND rejection of unexpected keys. The model will eventually send every wrong shape.
- Whitelist strict-enum values headed to external systems. Model-generated slugs/networks/plans get mapped through a server-side table — never passed through, even when the prompt "guarantees" the format.
- Authorization never derives from model output. The model can propose; only server-recorded state + explicit user action can approve. Never let a model-visible tool perform destructive/financial writes directly — gate writes behind a human-approval step bound server-side (proposal pattern). Never trust a model's claim about what the user consented to.
- Prompt injection is transitive: any tool result containing third-party text (web pages, tickets, emails) is a channel for instructions to your model. Treat tool results as data in your prompt design; never give a model simultaneously (a) exposure to untrusted text and (b) unsupervised dangerous capabilities.
Determinism where it matters
Route load-bearing guarantees through code, not prompts: format enforcement, redaction/scrubbing of sensitive figures, filtering which tools the model sees, output length caps. A prompt instruction is a strong suggestion; a deterministic post-processor is a guarantee. Use both (prompt = primary, code = backstop).
Prompt & model changes are behavior changes
- Never ship a prompt/model change on vibes. Run the project's eval suite; if none exists for the behavior you're changing, write at least a smoke set first. A model swap that "just works" in one manual test can regress safety/format behaviors discovered only under repetition.
- Cache economics: providers cache the prompt prefix. Keep stable content (system prompt, tool defs) first and byte-identical across turns; put variable content last. A "harmless" reordering or timestamp in the system prompt can silently multiply token cost.
- Pin model IDs explicitly; know each pinned model's parameter quirks (thinking/effort defaults differ per model — verify, don't assume compatibility when swapping).
Streaming and the agent loop
- Handle the full event grammar: partial deltas, tool-use blocks interleaved with text, stop reasons (
max_tokensmid-JSON!), and error events mid-stream. Test the abort path — client disconnects mid-generation must clean up. - Agent loops need: an iteration cap, per-tool timeouts, token/cost budget, and dedupe/idempotency on tool execution (retried turns re-issue tool calls).
- Retries: retry transient API errors with backoff; NEVER blind-retry a turn whose tool side-effects may have executed.
Cost/latency hygiene
Log tokens + cost per turn from day one (you cannot fix what you don't attribute). Trim tool results before feeding them back (models don't need 400-row payloads). Choose the model tier per call site deliberately — classification/extraction rarely needs the flagship.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.