9 views
Seniors already ban child_process.exec with unsanitized input, aws-sdk v2 in new code, and hard-coded credentials—then the coding agent cheerfully regenerates them. Negative constraints encode those bans in versioned system prompts and in machine-checkable validators so codegen fails closed when it ignores the list.
⚡ TL;DR: Maintain a banned_apis.yaml sourced from lint rules; inject a compressed NEGATIVES block into system prompts; validate model patches with AST/grep gates before apply; version with Prompt Management. Pair with LLM output validators and Bedrock Guardrails.
Negative Constraints in Prompts: production guidance
yaml
CI publishes a compact prompt fragment:
# banned_apis.yaml — generated from eslint/deny + security ADRs
version: 17
banned:
- id: no-exec-string
match: { module: "child_process", exports: ["exec", "execSync"] }
reason: "Use execFile with arg arrays; see ADR-0142"
- id: no-aws-sdk-v2
match: { module: "aws-sdk" }
reason: "Use @aws-sdk/* v3 clients"
- id: no-hardcoded-secrets
match: { regex: "(AKIA[0-9A-Z]{16}|secretAccessKey\\s*[:=])" }
reason: "Secrets belong in SSM/Secrets Manager"
- id: no-verifalse-tls
match: { regex: "rejectUnauthorized\\s*:\\s*false" }
reason: "Never disable TLS verification"
deprecated_modules:
- "request"
- "moment"
text
## NEGATIVES (must not generate)
- Do NOT import aws-sdk (v2). Use @aws-sdk/* v3.
- Do NOT call child_process.exec/execSync with string commands.
- Do NOT disable TLS (rejectUnauthorized:false).
- Do NOT embed AKIA… keys or secretAccessKey literals.
If a task seems to require a banned API, explain and propose the approved alternative.
Prompt + validator sandwich
typescript
import banned from "./banned_apis.json";
function systemPrompt(task: string): string {
return [
BASE_CODER_PROMPT,
renderNegatives(banned), // versioned fragment
`Task:\n${task}`,
].join("\n\n");
}
function assertNoBanned(patch: string): void {
for (const rule of banned.banned) {
if (rule.match.module && importUses(patch, rule.match)) {
throw new Error(`banned:${rule.id}:${rule.reason}`);
}
if (rule.match.regex && new RegExp(rule.match.regex).test(patch)) {
throw new Error(`banned:${rule.id}:${rule.reason}`);
}
}
}
typescript
Do not rely on prompt-only bans without AST/grep gates — models drift; lint is the backstop.
async function safeApply(task: string) {
const patch = await generatePatch(systemPrompt(task));
try {
assertNoBanned(patch);
} catch (e) {
// One repair loop with the violation named
const repaired = await generatePatch(
systemPrompt(task) + `\nREPAIR: ${String(e)}. Use approved alternatives only.`,
);
assertNoBanned(repaired); // fail closed on second violation
return applyPatch(repaired);
}
return applyPatch(patch);
}
Keep negatives short and current
| Practice | Why |
|---|---|
| Cap NEGATIVES block ~40–60 lines | Long lists get ignored |
| Generate from lint deny lists | Avoid prompt/lint drift |
| Version + changelog | Know what prod agents saw |
| Prefer “use X instead” | Models need alternatives |
Eval the negatives
python
Wire into CI canaries so prompt edits that drop NEGATIVES fail loud.
# canary: agent must refuse or rewrite banned patterns
cases = load_yaml("evals/banned_api_tasks.yaml")
for c in cases:
patch = run_agent(c["task"])
assert not violates(patch, banned), c["id"]
assert c["approved_alternative_marker"] in patch
Closing checklist
Dos – Generate NEGATIVES from the same source as lint deny rules – Inject a short versioned fragment into system prompts – Validate patches with AST/regex gates; one repair then fail closed – Offer approved alternatives in the prompt text – Canary banned-API tasks on every prompt release Donts – Do not rely on prose bans alone – Do not paste a 500-line policy into every prompt – Do not let prompt and eslint diverge – Do not silently strip banned lines without telling the user – Do not forget secret regexes (keys, tokens) in the same listRelated reading
Last updated on September 11, 2026 Related: Code Generation with LLMs: Structured Output, AST Manipulation, and Avoiding Hallucinated APIs; Claude as a Code Generation Engine: System Prompts and Patterns That Ship Production Code; REST API Design Best Practices: The Patterns That Make APIs a Joy to Use.Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- Css Animation Performance: Performance-Optimized Motion for Modern UIs
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
