# Reference Templates

Complete file templates for LLM command integration. Replace `{project}`,
`{agent-name}`, `{domain}` with project-specific values.

## DSL: Main entry (`dsl/{project}-dsl.yaml`)

```yaml
version: 1
system:
  id: {project}
  name: "{Project} Agent System"
  default_workflow_order:
    - {workflow-1}
    - {workflow-2}
    - {workflow-3}

agents: { $ref: "./agents/" }
tasks: { $ref: "./tasks.yaml" }
handoff_types: { $ref: "./handoff-types.yaml" }

guardrails:
  output-schema-conformance:
    description: >-
      Ensure all agent outputs conform to the result handoff schema.
      Validation is performed at runtime via Zod.
    scope:
      agents:
        - {agent-name}
      tasks:
        - {task-1}
        - {task-2}
        - {task-3}
    rationale: >-
      Structured output conformance is critical for CLI parsing
      and downstream tooling integration.

  no-{dangerous-action}:
    description: >-
      Agent must never {perform dangerous action}.
    scope:
      agents:
        - {agent-name}
    rationale: >-
      The agent operates in read-only analysis mode.

  confidence-threshold:
    description: >-
      Findings with confidence below 0.5 must include an explicit
      uncertainty disclaimer in their recommendation.
    scope:
      tasks:
        - {task-1}
        - {task-2}
    rationale: >-
      Low-confidence findings without disclaimers may mislead users.

guardrail_policies:
  {domain}-safety-policy:
    description: >-
      Groups all guardrails for the {agent-name} agent.
    rules:
      - guardrail: output-schema-conformance
        severity: critical
        action: block
      - guardrail: no-{dangerous-action}
        severity: critical
        action: block
      - guardrail: confidence-threshold
        severity: warning
        action: warn

workflow:
  {workflow-1}:
    description: "{Workflow 1 description}"
    trigger: cli-command
    entry_conditions:
      - "{Entry condition}"
    steps:
      - type: delegate
        task: {task-1}
        from_agent: {agent-name}

  {workflow-2}:
    description: "{Workflow 2 description}"
    trigger: cli-command
    entry_conditions:
      - "{Entry condition}"
    steps:
      - type: delegate
        task: {task-2}
        from_agent: {agent-name}

  {workflow-3}:
    description: "{Workflow 3 description}"
    trigger: cli-command
    entry_conditions:
      - "{Entry condition}"
    steps:
      - type: delegate
        task: {task-3}
        from_agent: {agent-name}
```

## DSL: Agent (`dsl/agents/{agent-name}.yaml`)

```yaml
{agent-name}:
  role_name: "{Agent Role Name}"
  purpose: >-
    {Describe the agent's purpose. What domain knowledge does it have?
    What can it do that static rules cannot?}
  mode: read-only
  can_read_artifacts: []
  can_write_artifacts: []
  can_invoke_agents: []
  can_execute_tools: []
  can_return_handoffs:
    - {result-handoff-1}
    - {result-handoff-2}
    - {result-handoff-3}
  responsibilities:
    - "{Responsibility 1}"
    - "{Responsibility 2}"
    - "{Responsibility 3}"
  constraints:
    - "Do not claim safety without citing specific assumptions"
    - "Output must conform to AgentAuditResult schema (summary, riskLevel, findings, recommendedActions, metadata)"
    - "Findings must use {project} category vocabulary ({cat-1}, {cat-2}, ...)"
    - "Each finding must include a recommendation when severity is warning or above"
  rules:
    - id: "R-{PREFIX}-001"
      description: "{Rule 1}"
      severity: mandatory
    - id: "R-{PREFIX}-002"
      description: "{Rule 2}"
      severity: mandatory
  escalation_criteria:
    - condition: "Input cannot be parsed or is structurally invalid"
      action: stop_and_report
    - condition: "Input contains dynamic content that cannot be statically analyzed"
      action: stop_and_report
```

## DSL: Tasks (`dsl/tasks.yaml`)

```yaml
{task-1}:
  description: "{Task 1: audit-style}"
  target_agent: {agent-name}
  allowed_from_agents:
    - {agent-name}
  workflow: {workflow-1}
  input_artifacts: []
  invocation_handoff: {request-handoff}
  result_handoff: {result-handoff-1}
  responsibilities:
    - "Evaluate all items for risks"
    - "Classify findings by severity and category"
  completion_criteria:
    - "All items evaluated"
    - "Findings classified by severity and category"
    - "Output conforms to AgentAuditResult schema"

{task-2}:
  description: "{Task 2: proposal-style}"
  target_agent: {agent-name}
  allowed_from_agents:
    - {agent-name}
  workflow: {workflow-2}
  input_artifacts: []
  invocation_handoff: {request-handoff}
  result_handoff: {result-handoff-2}
  responsibilities:
    - "Identify problems requiring structured proposals"
    - "Generate valid, actionable proposals"
  completion_criteria:
    - "Proposal is complete and actionable"
    - "Each step has valid output"
    - "recommendedActions include concrete edit_file actions"

{task-3}:
  description: "{Task 3: explain-style}"
  target_agent: {agent-name}
  allowed_from_agents:
    - {agent-name}
  workflow: {workflow-3}
  input_artifacts: []
  invocation_handoff: {request-handoff}
  result_handoff: {result-handoff-3}
  responsibilities:
    - "Summarize output for non-expert readers"
    - "Provide concrete next steps as recommendedActions"
  completion_criteria:
    - "Explanation accurately summarizes the command output"
    - "Action items are concrete and actionable"
    - "Technical terms explained for non-expert readers"
```

## DSL: Handoff types (`dsl/handoff-types.yaml`)

**Preferred**: Use `$ref` to `cli-contract.yaml` AgentAuditResult as SSoT
(this is how cli-contracts itself does it):

```yaml
{request-handoff}:
  version: 1
  description: Request to execute a {project} audit task
  schema:
    type: object
    properties:
      task_id:
        type: string
        description: Identifier of the task to execute
      context:
        type: string
        description: Built context string
    required:
      - task_id

{result-handoff-1}:
  version: 1
  description: >-
    Result of a {project} audit task.
    Schema references cli-contract.yaml AgentAuditResult as SSoT.
  schema:
    $ref: '../cli-contract.yaml#/components/schemas/AgentAuditResult'
```

**Fallback** (when agent-contracts cannot resolve cross-file `$ref` at
generate time): Inline the schema with a comment noting the SSoT.

The inlined schema must follow the **cli-contracts reference specification**:

```yaml
{result-handoff-1}:
  version: 1
  description: >-
    Result of a {project} audit task.
    Inlined from cli-contract.yaml AgentAuditResult (SSoT).
  schema:
    type: object
    required: [summary, riskLevel, findings]
    properties:
      summary:
        type: string
      riskLevel:
        type: string
        enum: [low, medium, high, critical]
      findings:
        type: array
        items:
          # AgentFinding — cli-contracts reference schema
          type: object
          required: [severity, category, message]
          properties:
            id:
              type: string
              description: Unique finding identifier
            severity:
              type: string
              enum: [info, warning, error, critical]
            category:
              type: string
              description: Finding category (domain-specific vocabulary)
            target:
              type: string
              description: Target of the finding (file path, command ID, etc.)
            location:
              type: string
              description: Location within the target
            message:
              type: string
            recommendation:
              type: string
            confidence:
              type: number
              minimum: 0
              maximum: 1
              description: Confidence score (0-1) for LLM-generated findings
            evidence:
              type: array
              items:
                type: object
                properties:
                  type: { type: string }
                  content: { type: string }
                  source: { type: string }
            details:
              type: object
              additionalProperties: true
      recommendedActions:
        type: array
        items:
          # AgentRecommendedAction — cli-contracts reference schema
          type: object
          required: [kind, title]
          properties:
            kind:
              type: string
              enum: [run_command, edit_file, review, confirm, block, ignore]
            title:
              type: string
            command:
              type: string
              description: CLI command to run (for run_command kind)
            target:
              type: string
              description: Target file or resource
            rationale:
              type: string
      metadata:
        type: object
        properties:
          tool: { type: string }
          command: { type: string }
          version: { type: string }
          generatedAt: { type: string }
          adapter: { type: string }
          model: { type: string }
```

**Domain-specific result types** extend the base shape with additional
fields while keeping all AgentAuditResult fields intact:

```yaml
{result-handoff-2}:
  version: 1
  description: >-
    Domain-specific result extending AgentAuditResult.
    Adds {domain-specific fields} alongside base fields.
  schema:
    type: object
    required: [summary, riskLevel, findings]
    properties:
      # All AgentAuditResult base fields (same as above)
      summary: { type: string }
      riskLevel: { type: string, enum: [low, medium, high, critical] }
      findings:
        type: array
        items: { ... }  # Same AgentFinding shape
      recommendedActions:
        type: array
        items: { ... }  # Same AgentRecommendedAction shape
      metadata: { ... }

      # Domain-specific extensions:
      phases:
        type: array
        items:
          type: object
          required: [name, sql]
          properties:
            name: { type: string }
            sql: { type: string }
            description: { type: string }

{result-handoff-3}:
  version: 1
  description: >-
    Explain-style result extending AgentAuditResult.
  schema:
    type: object
    required: [summary, riskLevel, findings]
    properties:
      # All AgentAuditResult base fields
      summary: { type: string }
      riskLevel: { type: string, enum: [low, medium, high, critical] }
      findings: { ... }
      recommendedActions: { ... }
      metadata: { ... }

      # Domain-specific extension:
      explanation:
        type: string
        description: Human-readable explanation of the command output
```

## DSL: Runtime config (`dsl/agent-runtime.config.yaml`)

```yaml
dsl: ./{project}-dsl.yaml
generated_dir: ../src/generated/dsl
```

## TypeScript: `src/agents/types.ts`

```typescript
import type { {ResultType} } from "../generated/dsl/handoffs.js";

export type TaskId =
  | "{task-1}"
  | "{task-2}"
  | "{task-3}";

export interface AgentConfig {
  adapter?: string;
  model?: string;
  temperature?: number;
}

export interface AgentOptions {
  showPrompt?: boolean;
  failOn?: "warning" | "error" | "critical";
}

export interface AgentRunResult {
  taskId: TaskId;
  data: {ResultType} | null;
  raw: string;
  prompt: string;
  showPrompt: boolean;
  status: "success" | "error" | "escalation" | "validation_error";
  errorMessage?: string;
  followUpsUsed: number;
  retriesUsed: number;
}
```

## TypeScript: `src/agents/orchestrator.ts`

```typescript
import type { AgentConfig, AgentOptions, AgentRunResult, TaskId } from "./types.js";

export const EXIT_RUNTIME_MISSING = 11;
export const EXIT_ADAPTER_ERROR = 12;

async function createAdapter(runtimePkg: string, name: string, config: AgentConfig) {
  switch (name) {
    case "mock": {
      const mod = await import(`${runtimePkg}/adapters/mock`);
      return new mod.MockAdapter();
    }
    case "cursor": {
      const mod = await import(`${runtimePkg}/adapters/cursor-sdk`);
      const apiKey = process.env.CURSOR_API_KEY;
      if (!apiKey) throw new Error("CURSOR_API_KEY environment variable is required");
      return mod.CursorSdkAdapter.create({ apiKey, model: config.model });
    }
    case "openai": {
      const mod = await import(`${runtimePkg}/adapters/openai-agents-sdk`);
      return new mod.OpenAIAgentsSdkAdapter({ model: config.model, maxTurns: 1 });
    }
    case "gemini": {
      const mod = await import(`${runtimePkg}/adapters/gemini-sdk`);
      return new mod.GeminiSdkAdapter({
        apiKey: process.env.GEMINI_API_KEY,
        model: config.model,
        temperature: config.temperature,
      });
    }
    case "claude": {
      const mod = await import(`${runtimePkg}/adapters/claude-agent-sdk`);
      return new mod.ClaudeAgentSdkAdapter({
        model: config.model,
        tools: ["Read", "Glob", "Grep"],
        permissionMode: "bypassPermissions",
      });
    }
    default:
      throw new Error(`Unsupported adapter: "${name}". Available: mock, cursor, openai, gemini, claude.`);
  }
}

export async function runAgentTask(
  userRequest: string,
  taskId: TaskId,
  config: AgentConfig,
  options: AgentOptions,
): Promise<AgentRunResult> {
  if (options.showPrompt) {
    return { taskId, data: null, raw: "", prompt: userRequest, showPrompt: true,
             status: "success", followUpsUsed: 0, retriesUsed: 0 };
  }

  const RUNTIME_PKG = ["agent-contracts", "runtime"].join("-");

  let runTask;
  try {
    const runtime = await import(RUNTIME_PKG);
    runTask = runtime.runTask;
  } catch {
    throw Object.assign(
      new Error("agent-contracts-runtime is not installed.\n  npm install agent-contracts-runtime"),
      { exitCode: EXIT_RUNTIME_MISSING },
    );
  }

  let agentRegistry, taskRegistry, handoffSchemas;
  try {
    const dsl = await import("../generated/dsl/index.js");
    agentRegistry = dsl.agentRegistry;
    taskRegistry = dsl.taskRegistry;
    handoffSchemas = dsl.handoffSchemas;
  } catch {
    agentRegistry = {}; taskRegistry = {}; handoffSchemas = {};
  }

  let adapter;
  try {
    adapter = await createAdapter(RUNTIME_PKG, config.adapter ?? "mock", config);
  } catch (err) {
    throw Object.assign(err as Error, { exitCode: EXIT_ADAPTER_ERROR });
  }

  const result = await runTask(adapter, taskId, { user_request: userRequest }, {
    maxFollowUps: 3, maxRetries: 1, agentRegistry, taskRegistry, handoffSchemas,
  });

  const outcome = result.outcome;
  return {
    taskId,
    data: outcome.status === "success" ? outcome.data : null,
    raw: (outcome.raw as string) ?? "",
    prompt: userRequest,
    showPrompt: false,
    status: outcome.status,
    errorMessage:
      outcome.status === "error" ? outcome.message :
      outcome.status === "escalation" ? outcome.reason :
      outcome.status === "validation_error" ? outcome.errors?.message :
      undefined,
    followUpsUsed: result.follow_ups_used,
    retriesUsed: result.retries_used,
  };
}
```

## TypeScript: `src/agents/formatter.ts`

```typescript
import type { AgentRunResult, AgentOptions } from "./types.js";

export function computeExitCode(result: AgentRunResult, options: AgentOptions): number {
  if (result.showPrompt) return 0;
  if (result.status !== "success" || !result.data) return 1;

  const failOn = options.failOn ?? "error";
  const order = ["info", "warning", "error", "critical"] as const;
  const threshold = order.indexOf(failOn);
  const hasBlocking = result.data.findings.some(
    (f) => order.indexOf(f.severity) >= threshold,
  );
  return hasBlocking ? 10 : 0;
}

export function formatResultText(result: AgentRunResult): string {
  if (result.showPrompt) return result.prompt;
  if (result.status !== "success" || !result.data) {
    return result.errorMessage ?? `Task failed: ${result.status}`;
  }
  const d = result.data;
  const lines = [`Risk Level: ${d.riskLevel.toUpperCase()}`, `Summary: ${d.summary}`, ""];
  if (d.findings.length > 0) {
    lines.push(`Findings (${d.findings.length}):`, "");
    for (const f of d.findings) {
      const icon = f.severity === "critical" || f.severity === "error" ? "✖"
                 : f.severity === "warning" ? "⚠" : "ℹ";
      lines.push(`  ${icon} [${f.category}] ${f.message}`);
      if (f.target) lines.push(`    Target: ${f.target}`);
      if (f.location) lines.push(`    Location: ${f.location}`);
      if (f.recommendation) lines.push(`    Recommendation: ${f.recommendation}`);
      if (f.confidence != null) lines.push(`    Confidence: ${f.confidence}`);
      lines.push("");
    }
  }
  if (d.recommendedActions?.length) {
    lines.push("Recommended Actions:");
    for (const a of d.recommendedActions) {
      lines.push(`  - [${a.kind}] ${a.title}`);
      if (a.command) lines.push(`    $ ${a.command}`);
      if (a.target) lines.push(`    Target: ${a.target}`);
      if (a.rationale) lines.push(`    Rationale: ${a.rationale}`);
    }
  }
  return lines.join("\n");
}

export function formatResultJson(result: AgentRunResult): string {
  if (result.showPrompt) return JSON.stringify({ showPrompt: true, prompt: result.prompt }, null, 2);
  if (!result.data) return JSON.stringify({ error: result.errorMessage, status: result.status }, null, 2);
  return JSON.stringify(result.data, null, 2);
}
```

## CLI registration pattern

```typescript
import { Command } from "commander";

const audit = new Command("audit")
  .description("Semantic safety audit via LLM")
  .argument("[target]", "file or directory to audit")
  .option("--adapter <name>", "LLM adapter (cursor, openai, gemini, claude, mock)", "mock")
  .option("--model <name>", "Model name to pass to the adapter")
  .option("--show-prompt", "Output the constructed prompt without calling the LLM API")
  .option("--fail-on <level>", "Minimum severity for non-zero exit", "error")
  .option("-o, --output <file>", "Write result to file instead of stdout")
  .option("--report-format <fmt>", "Output format (json, text, yaml)", "json")
  .action(async (target, opts) => {
    // load config, call command handler
  });

program.addCommand(audit);
```

## cli-contract.yaml: LLM command options + x-agent

```yaml
commands:
  audit:
    description: "Semantic safety audit via LLM"
    arguments:
      - name: target
        index: 0
        required: false
        description: "File or directory to audit"
        schema:
          type: string

    options:
      - name: adapter
        description: LLM adapter to use.
        valueName: name
        schema:
          type: string
          enum: [mock, cursor, claude, openai, gemini]

      - name: model
        description: Model name to pass to the adapter.
        valueName: name
        schema:
          type: string

      - name: show-prompt
        description: Output the constructed prompt without calling the LLM API.
        schema:
          type: boolean
          default: false

      - name: fail-on
        description: Minimum severity that causes a non-zero exit.
        valueName: level
        schema:
          type: string
          enum: [warning, error, critical]
          default: error

      - name: output
        aliases: [o]
        description: Write result to a file instead of stdout.
        valueName: file
        schema:
          type: string
        file:
          mode: write
          mediaType: application/json
          encoding: utf-8

      - name: report-format
        description: Output format for the audit report.
        valueName: fmt
        schema:
          type: string
          enum: [json, text, yaml]
          default: json

    x-agent:
      riskLevel: low
      requiresConfirmation: false
      idempotent: true
      sideEffects: [network]
      sideEffectNote: >-
        Network calls to LLM provider when adapter is not mock.
        Filesystem write only when --output is specified.
      safeDryRunOption: show-prompt
      expectedDurationMs: 120000
      retryableExitCodes: [1, 12]

    exits:
      '0':
        description: Completed without blocking findings.
        stdout:
          format: '{options.report-format}'
          schema:
            $ref: '#/components/schemas/AgentAuditResult'
      '1':
        description: Unexpected error.
        stderr:
          format: json
          schema:
            $ref: '#/components/schemas/Error'
      '3':
        description: Input validation/parse failed.
        stderr:
          format: json
          schema:
            $ref: '#/components/schemas/Error'
      '10':
        description: Completed with blocking findings.
        stdout:
          format: '{options.report-format}'
          schema:
            $ref: '#/components/schemas/AgentAuditResult'
      '11':
        description: Runtime dependency missing (agent-contracts-runtime).
        stderr:
          format: json
          schema:
            $ref: '#/components/schemas/Error'
      '12':
        description: Adapter initialization error.
        stderr:
          format: json
          schema:
            $ref: '#/components/schemas/Error'
```

## cli-contract.yaml: AgentAuditResult schema (in components/schemas)

This is the reference specification from cli-contracts. Include it in
your project's `cli-contract.yaml` `components/schemas` section:

```yaml
components:
  schemas:
    AgentFinding:
      type: object
      description: >-
        A single finding from an agent audit.
        Reference schema for AI agent interoperability.
      required: [severity, category, message]
      properties:
        id:
          type: string
          description: Unique finding identifier.
        severity:
          type: string
          enum: [info, warning, error, critical]
        category:
          type: string
          description: Finding category (domain-specific vocabulary).
        target:
          type: string
          description: Target of the finding (file path, command ID, etc.).
        location:
          type: string
          description: Location within the target.
        message:
          type: string
        recommendation:
          type: string
        confidence:
          type: number
          minimum: 0
          maximum: 1
          description: Confidence score (0-1) for LLM-generated findings.
        evidence:
          type: array
          items:
            $ref: '#/components/schemas/AgentEvidence'
        details:
          type: object
          additionalProperties: true

    AgentEvidence:
      type: object
      properties:
        type: { type: string }
        content: { type: string }
        source: { type: string }

    AgentRecommendedAction:
      type: object
      description: >-
        A recommended action from an agent audit.
        Reference schema for AI agent interoperability.
      required: [kind, title]
      properties:
        kind:
          type: string
          enum: [run_command, edit_file, review, confirm, block, ignore]
        title:
          type: string
        command:
          type: string
          description: CLI command to run (for run_command kind).
        target:
          type: string
          description: Target file or resource.
        rationale:
          type: string

    AgentAuditResult:
      type: object
      description: >-
        Top-level result from an agent audit.
        Reference schema for AI agent interoperability.
      required: [summary, riskLevel, findings]
      properties:
        summary:
          type: string
        riskLevel:
          type: string
          enum: [low, medium, high, critical]
        findings:
          type: array
          items:
            $ref: '#/components/schemas/AgentFinding'
        recommendedActions:
          type: array
          items:
            $ref: '#/components/schemas/AgentRecommendedAction'
        metadata:
          type: object
          properties:
            tool: { type: string }
            command: { type: string }
            version: { type: string }
            generatedAt: { type: string }
            adapter: { type: string }
            model: { type: string }
```
