his layer: custom slash commands for prompt templating, hooks for pre/post execution validation, headless mode (claude -p) for non-interactive runs, and subagent delegation for scoped task isolation. The architecture below stitches these primitives into a durable, version-controlled artifact.
Step 1: Define the Routine Contract
Every routine must declare its inputs, expected outputs, and verification criteria. This contract prevents the agent from improvising outside bounded parameters. Inputs typically include target branches, file patterns, or issue IDs. Outputs should be structured (e.g., JSON summaries, diff paths, or PR metadata). Verification gates enforce checks like test suite passes, lint compliance, or dry-run validation before proceeding.
Step 2: Orchestrate with a TypeScript Runner
While Claude Code handles the reasoning layer, a lightweight orchestrator manages execution flow, state passing, and error handling. The runner reads a declarative configuration, invokes the agent in headless mode, applies hooks for validation, and delegates complex subtasks to isolated subagents.
import { execSync } from 'child_process';
import { readFileSync } from 'fs';
import { join } from 'path';
interface RoutineStep {
id: string;
description: string;
prompt_template: string;
validation_hook?: string;
timeout_ms: number;
}
interface RoutineConfig {
name: string;
version: string;
steps: RoutineStep[];
global_hooks: {
pre_run?: string;
post_run?: string;
};
}
export class WorkflowOrchestrator {
private config: RoutineConfig;
private executionLog: string[] = [];
constructor(configPath: string) {
const raw = readFileSync(configPath, 'utf-8');
this.config = JSON.parse(raw);
}
async execute(targetDir: string): Promise<void> {
console.log(`[Routine] Starting: ${this.config.name} v${this.config.version}`);
if (this.config.global_hooks.pre_run) {
this.runHook(this.config.global_hooks.pre_run, targetDir);
}
for (const step of this.config.steps) {
console.log(`[Step ${step.id}] ${step.description}`);
const prompt = this.interpolatePrompt(step.prompt_template, targetDir);
const result = this.runHeadlessAgent(prompt, targetDir, step.timeout_ms);
this.executionLog.push(`[${step.id}] ${result}`);
if (step.validation_hook) {
this.runHook(step.validation_hook, targetDir);
}
}
if (this.config.global_hooks.post_run) {
this.runHook(this.config.global_hooks.post_run, targetDir);
}
console.log('[Routine] Execution complete. Review logs before merging.');
}
private runHeadlessAgent(prompt: string, cwd: string, timeout: number): string {
const escapedPrompt = prompt.replace(/"/g, '\\"');
const cmd = `claude -p "${escapedPrompt}" --output-format json`;
return execSync(cmd, { cwd, timeout, encoding: 'utf-8' });
}
private runHook(hookCmd: string, cwd: string): void {
try {
execSync(hookCmd, { cwd, stdio: 'inherit' });
} catch (err) {
throw new Error(`[Hook Failure] ${hookCmd} exited with non-zero status.`);
}
}
private interpolatePrompt(template: string, cwd: string): string {
return template
.replace('{{CWD}}', cwd)
.replace('{{TIMESTAMP}}', new Date().toISOString());
}
}
Step 3: Architecture Decisions & Rationale
- Declarative Configuration over Imperative Scripts: Storing routines as JSON/YAML enables version control, team sharing, and diff tracking. The orchestrator remains thin; all logic lives in the config.
- Headless Execution (
claude -p): Non-interactive mode removes UI friction and enables CI/CD integration. It forces the agent to produce structured output rather than conversational filler.
- Explicit Validation Hooks: Pre/post hooks act as circuit breakers. If a dependency bump introduces a breaking change, the hook fails fast before the routine proceeds. This prevents silent corruption.
- Subagent Delegation: Complex routines should split work. The main orchestrator handles flow control; subagents receive scoped prompts with explicit file boundaries and output contracts. This reduces context window fragmentation and improves determinism.
Pitfall Guide
1. The Black Box Automation Trap
Explanation: Packaging a workflow you haven't manually validated turns misunderstandings into automated failures. An AI routine that merges breaking changes without human oversight is worse than manual execution.
Fix: Run the workflow manually with the agent 2-3 times. Read every step, verify outputs, and only then encode it into a routine. Always include a dry-run flag and mandatory human sign-off before production merges.
2. Context Window Fragmentation
Explanation: Long routines that pass unbounded file lists or entire codebases to the agent cause context dilution. The model loses focus, skips validation steps, or hallucinates file contents.
Fix: Scope inputs explicitly. Use glob patterns, commit hashes, or explicit file lists. Pass state via structured JSON rather than natural language summaries. Limit each step to a single responsibility.
3. Routine Decay & Codebase Drift
Explanation: Routines assume a stable codebase structure. When architecture shifts, file paths change, or test frameworks update, stale routines fail silently or produce incorrect diffs.
Fix: Version-pin routine configurations alongside major releases. Implement automated regression tests that execute routines against a snapshot repository weekly. Flag routines that fail validation for manual review.
4. Subagent Scope Creep
Explanation: Delegation without strict contracts causes subagents to overreach. They may modify unrelated files, ignore output formats, or hang indefinitely on ambiguous tasks.
Fix: Define explicit input/output schemas for each subagent. Set hard timeouts. Require subagents to return structured JSON with status, modified files, and validation results. Reject outputs that don't match the schema.
5. Hook Failure Cascades
Explanation: Validation hooks that lack proper error handling can crash the entire routine or mask failures. A flaky linter or network timeout in a hook may abort a valid workflow.
Fix: Wrap hooks in retry logic with exponential backoff. Separate critical gates (must pass) from advisory checks (warn only). Log hook outputs separately for debugging.
6. Ignoring Deterministic Fallbacks
Explanation: AI routines are probabilistic. When the model encounters edge cases, it may deviate from the expected path, producing inconsistent results across runs.
Fix: Implement deterministic fallbacks for critical steps. If the AI output fails validation, trigger a traditional script or prompt the developer for manual intervention. Never rely solely on stochastic generation for production-critical paths.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| High-frequency, deterministic tasks (e.g., changelog generation) | Packaged AI Routine | Balances flexibility with repeatability; reduces manual overhead | Low (config maintenance) |
| Critical infrastructure changes (e.g., database migrations) | Traditional CI/CD Pipeline | Requires strict determinism and rollback capabilities | High (implementation & testing) |
| Exploratory or creative tasks (e.g., feature architecture design) | Ad-Hoc Prompting | AI reasoning adds value; rigid workflows hinder iteration | Medium (developer time) |
| Multi-step workflows with external API dependencies | Packaged AI Routine + Hook Validation | AI handles orchestration; hooks verify external state | Medium (hook development) |
Configuration Template
{
"name": "dependency-audit-pr",
"version": "1.2.0",
"description": "Scans for outdated packages, generates upgrade PR with validation",
"global_hooks": {
"pre_run": "npm run lint:check && npm run test:unit -- --passWithNoTests",
"post_run": "git diff --stat"
},
"steps": [
{
"id": "scan",
"description": "Identify outdated dependencies and security advisories",
"prompt_template": "Analyze {{CWD}}/package.json. List packages with major version bumps or known CVEs. Output JSON with fields: package, current, latest, severity.",
"validation_hook": "node scripts/validate-scan-output.js",
"timeout_ms": 30000
},
{
"id": "upgrade",
"description": "Apply safe upgrades and run integration tests",
"prompt_template": "Update packages from the scan output that are marked 'minor' or 'patch'. Run npm install and execute integration tests. Report pass/fail status.",
"validation_hook": "npm run test:integration",
"timeout_ms": 120000
},
{
"id": "pr-draft",
"description": "Generate pull request description and changelog",
"prompt_template": "Create a PR description summarizing the dependency changes. Include breaking change warnings, test results, and migration steps. Output markdown.",
"validation_hook": null,
"timeout_ms": 15000
}
]
}
Quick Start Guide
- Install Prerequisites: Ensure Claude Code is installed and authenticated. Verify
claude -p executes successfully in your terminal.
- Create Routine Config: Save the JSON template above as
routines/dependency-audit.json in your project root. Adjust prompts and hooks to match your stack.
- Initialize Orchestrator: Place the TypeScript runner in
scripts/routine-runner.ts. Compile with tsc or run via ts-node.
- Execute Dry-Run: Run
node scripts/routine-runner.js --dry-run routines/dependency-audit.json. Review the output diff and validation logs.
- Schedule & Monitor: Add the routine to your CI pipeline or developer alias. Monitor execution logs for the first 5 runs to calibrate timeouts and validation thresholds.