llm-feature-engineering — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited llm-feature-engineering (Agent Skill) and scored it 91/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} is the classic direct prompt-injection phrasing. Placed in a skill body that the agent reads as trusted instructions, it tries to make the agent abandon its prior rules and follow whatever comes next — a full system-prompt override.
ignore/disregard/forget … previous instructions sentence.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
An LLM is a non-deterministic dependency — it can be wrong, slow, expensive, or manipulated. Treating it like fetchUser(id) produces flaky, unsafe features. Engineer around its nature: define a contract, constrain output, ground facts, measure quality with evals, handle failure modes, and never trust raw model text as correct ([[hardening]]).
LLM features are products — users need predictable behavior, fallbacks when AI fails, and clarity when output is machine-generated. "Demo magic" is not shipping.
Pairs with [[context-curation]] for prompt payload size, [[source-first]] for grounding, [[interface-design]] for tool schemas, [[resilience]] for timeouts/retries, [[observability]] for cost/quality/latency, [[test-first]] mindset for eval sets, [[incremental-delivery]] to ship slices, and [[launch-readiness]] for gradual rollout of AI behavior.
Also ask: should this be an LLM at all? Rules, regex, search, or classical ML often beat a general model for narrow tasks — cheaper, deterministic, auditable. Use LLM when language understanding, open-ended generation, or flexible reasoning is genuinely required.
Skip heavy LLM engineering for one-off internal scripts with no user impact — still validate outputs if they touch production data.
Work in order. Prompt tuning before task definition is wasted iteration.
Write what the feature must do in testable terms ([[spec-first]]):
| Field | Example |
|---|---|
| Input | User question + retrieved docs; ticket text; form fields |
| Output | JSON { summary, category, confidence }; user-visible reply; tool call only |
| Success | ≥90% category match on eval set; summary contains all key facts; p95 < 3s |
| Failure cost | Wrong medical dose = critical; wrong emoji suggestion = low |
| Out of scope | Model must not execute purchases, access arbitrary data |
Vague goals ("be helpful") are unmeasurable. One sentence output contract minimum.
Choose pattern:
| Pattern | Use when | Avoid when |
|---|---|---|
| Classification / extraction | Fixed labels, fields from text | Need creative prose |
| Generation | Drafts, explanations, transforms | Facts without sources |
| RAG | Answers must cite company data | Tiny static FAQ (use search) |
| Tool/agent | Multi-step actions in product | Simple single API call |
| Hybrid | Retrieve → extract → generate with schema | Over-agent for one lookup |
Don't default to the largest model:
| Factor | Tradeoff |
|---|---|
| Quality | Hard reasoning, long context → larger model |
| Latency | Chat UX → smaller/faster or streaming |
| Cost | High volume → smaller model + better prompt/RAG |
| Determinism | Lower temperature for extraction; higher for creative drafts |
Set token budgets — max input/output tokens, max retrieval chunks ([[context-curation]]). Instrument cost per request from day one ([[observability]]).
Re-evaluate when volume grows — a cheap model at scale beats a premium model on every request.
System prompt — stable rules: role, safety boundaries, output format, what never to do.
User/content — task instance; separate from untrusted data when possible ([[hardening]]).
Effective structure:
Role: You extract order issues from support tickets.
Task: Return category and one-line summary.
Output: JSON only, schema: { "category": enum, "summary": string, "confidence": 0-1 }
Rules:
- If unsure, category "unknown" and confidence < 0.5
- Do not invent order IDs not in the ticket
- Max summary 200 chars
Examples:
Input: "..." → Output: { ... }Few-shot examples — 2–5 representative cases, including edge cases (empty input, ambiguous). Update examples when evals fail — don't grow prompts without measurement.
Keep prompts minimal ([[context-curation]]) — every token is cost, latency, and distraction.
Model text is untrusted input to your app ([[hardening]]):
eval(), JSON.parse without schema, or SQL from model output without guardrailsconst parsed = schema.safeParse(modelOutput);
if (!parsed.success) return fallbackOrRetry(parsed.error);
// use parsed.data onlyFree-form text to users is OK for display — still sanitize HTML if rendered; don't pipe to downstream systems without validation.
For facts about your product, docs, or user data — model memory hallucinates ([[source-first]]):
RAG quality = retrieval quality. Eval retrieval separately from generation (did we fetch the right doc?).
Refresh index when source data changes; stale RAG is silent wrong answers.
Tools turn models into action surfaces — highest risk ([[interface-design]], [[hardening]]):
Bad tool: run_sql(query: string)
Good tool: search_orders(userId, status, limit) — scoped, typedLog tool calls with correlation id for audit ([[observability]], [[decision-docs]] for sensitive flows).
Without evals, prompt changes are guesswork ([[test-first]] mindset):
Golden set — 20–100+ real or realistic inputs with expected or rubric-scored outputs:
| Task type | Eval approach |
|---|---|
| Classification | Exact match or confusion matrix |
| Extraction | Field-level match; fuzzy for text |
| Generation | Rubric (human or LLM-judge), key facts present |
| RAG | Answer correct + citation correct |
Run evals:
Store eval cases in repo — version with prompts. Failed cases become regression additions.
Decide behavior for each — no silent undefined:
| Failure | Product behavior |
|---|---|
| Timeout | Bounded wait ([[resilience]]); fallback message or cached response |
| Rate limit / 5xx | Retry with backoff; degrade gracefully |
| Malformed output | Retry once → fallback |
| Refusal | Explain limitation; offer non-AI path |
| Low confidence | Don't auto-apply; human review queue |
| Model unavailable | Feature off or rule-based backup |
| Prompt injection | Don't follow user instructions to exfiltrate; layer defenses ([[hardening]]) |
Fallbacks should be designed, not "show error." User still completes the task.
Surface failures to telemetry — silent fallback hides systemic quality issues.
Any untrusted text in the prompt (user message, webpage, email, ticket) can try to override instructions:
Layers (none alone is sufficient):
### User input ### — weak alone but helpsFor high-risk (PII, payments, admin): human approval on actions; model proposes only.
Ship with dashboards ([[observability]]):
Alert on user-visible degradation — error spike, latency SLO, quality metric drop — not every failed parse.
Sample production traces for periodic human review — eval set drifts from reality.
Incremental delivery ([[incremental-delivery]], [[launch-readiness]]):
Human-in-the-loop where stakes are high — support suggestions, not auto-sent replies; clinician review for health; editor for published content.
Document AI disclosure where product/policy requires — users know output is machine-generated.
Version prompts and models in config — know what's live when debugging regressions.
Support ticket classification
Schema output → eval on labeled tickets → confidence threshold → route low confidence to human.
Doc Q&A (RAG)
Index pipeline → retrieval eval → generation with citations → validate cited chunks → fallback "no answer".
Chat copilot
Stream UX → token budget → injection layers → no tool without authz → rate limit per user.
Extraction to downstream API
Extract JSON → validate → map to API contract ([[interface-design]]) → never skip validation.
Agent with 3 tools
Allowlist → max 5 steps → log each call → timeout 30s → fallback to manual flow.
Summarization
Length limits → don't summarize secrets into output → eval key facts preserved.
Model upgrade
Same eval set on new model → compare cost/latency/quality → staged rollout.
Prompt hotfix in prod
Eval diff required → flag-gated deploy → watch override rate 24h.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.