# Workflows

End-to-end workflows for using the templating-vault system.

## Prompt-by-Reference Protocol

The core workflow that prevents LLM credential corruption. The parent agent never
passes prompt text through its own output. Instead, a script renders the prompt,
stores it in the vault, and returns only a short ID. The child agent retrieves the
prompt directly from the vault.

### Overview

```
Parent Agent                        Vault (scripts)                   Child Agent
     │                                    │                                │
     │  1. set credentials from env vars  │                                │
     │───────────────────────────────────>│                                │
     │                                    │                                │
     │  2. set session variables          │                                │
     │───────────────────────────────────>│                                │
     │                                    │                                │
     │  3. render --prepare               │                                │
     │───────────────────────────────────>│  (stores rendered prompt)      │
     │  <── returns only ID ──────────────│                                │
     │                                    │                                │
     │  4. launch child with just the ID  │                                │
     │────────────────────────────────────────────────────────────────────>│
     │                                    │                                │
     │                                    │  5. retrieve --id              │
     │                                    │<───────────────────────────────│
     │                                    │── prompt text + schema ───────>│
     │                                    │                                │
     │                                    │  6. extract (regex, per var)   │
     │                                    │<───────────────────────────────│
     │                                    │── stored, value_length ───────>│
     │                                    │                                │
     │                                    │  7. get (during execution)     │
     │                                    │<───────────────────────────────│
     │                                    │── value ──────────────────────>│
```

### Step-by-Step

**Step 0: One-time template setup (human or CI)**

Create a data directory with template files. Templates are Nunjucks text stored as
`value` files, with optional `schema.yaml` defining literal/non-literal variables.

```bash
mkdir -p /app/data/templates/imp_supervisor
cat > /app/data/templates/imp_supervisor/value << 'TPL'
Repository base url: {{ forgejo_url }}
forgejo pat: {{ forgejo_pat }}
tag prefix: {{ tag_prefix | default('AUTO-IMP') }}
The size of your worker pool: {{ max_workers | default(4) }}

Start processing and never finish.
TPL

cat > /app/data/templates/imp_supervisor/schema.yaml << 'S'
variables:
  forgejo_pat:
    literal: true
    type: hex
  forgejo_url:
    literal: true
    type: url
  tag_prefix:
    literal: true
  max_workers:
    literal: false
    type: positive_integer
S
```

Alternatively, bootstrap from a YAML definition:
```bash
npx --yes tsx init.ts --source definitions/templates.yaml --target /app/data/templates --on-exists fix
```

**Step 1: Primary agent bootstraps credentials**

At startup, the primary agent populates the vault from environment variables. Shell
expansion (`$(printenv)`) ensures the LLM never generates the raw values:

```bash
npx --yes tsx init.ts \
  --source definitions/global.yaml --target /tmp/globals --on-exists fix

npx --yes tsx set.ts \
  --key global.credentials.forgejo_pat \
  --value "$(printenv FORGEJO_PAT)" \
  --write-once --owner primary \
  --config /tmp/admin-config.yaml
# Repeat for all credentials and config values
```

The admin config gives `admin` access so literal keys can be set directly.

**Step 2: Set session-specific variables**

```bash
npx --yes tsx set.ts --key session.tag_prefix --value "AUTO-IMP" \
  --store-dir /tmp/globals --store-dir "session:/tmp/AUTO-IMP-SUP"

npx --yes tsx set.ts --key session.max_workers --value "4" \
  --store-dir /tmp/globals --store-dir "session:/tmp/AUTO-IMP-SUP"
```

**Step 3: Prepare the prompt**

```bash
npx --yes tsx render.ts --template-key templates.imp_supervisor --prepare \
  --store-dir /tmp/globals \
  --store-dir "session:/tmp/AUTO-IMP-SUP" \
  --store-dir "templates:/app/data/templates"
# Returns: {"prepared": true, "id": "prep-1776923319515-kks5ef", ...}
```

The ID is all the parent needs. The rendered prompt (with real credentials) is stored
in the vault, never in the LLM's output.

**Step 4: Launch child with only the ID**

The parent passes a minimal message to the subagent launch:
```
prepared_prompt_id: prep-1776923319515-kks5ef
Load the templating-vault skill and retrieve your prepared prompt.
Extract all literal variables per the schema, then begin your task.
```

**Step 5: Child retrieves the prompt**

```bash
npx --yes tsx retrieve.ts --id prep-1776923319515-kks5ef \
  --store-dir /tmp/globals
# Returns: {content: "...", variables: {forgejo_pat: {literal: true}, ...}}
```

The child reads `content` to understand its instructions. It reads `variables` to
know which ones need regex extraction.

**Step 6: Child extracts literal variables**

For each variable marked `literal: true` in the schema:

```bash
npx --yes tsx extract.ts \
  --source-key prepared.prep-1776923319515-kks5ef \
  --key session.forgejo_pat \
  --regex 'forgejo pat:\s*([a-f0-9]{40})' \
  --store-dir /tmp/globals --store-dir "session:/tmp/AUTO-IMP-SUP"
```

If the regex doesn't match, the script returns context hints. The child fixes its
regex and retries. The child never copies the value from its context.

**Step 7: Child uses values during execution**

```bash
npx --yes tsx get.ts --key session.forgejo_pat \
  --store-dir /tmp/globals --store-dir "session:/tmp/AUTO-IMP-SUP"
```

## Vault-Unaware Agent Flow

For agents that don't know the vault skill, the parent renders to a file instead:

```bash
npx --yes tsx render.ts --template-key templates.imp_supervisor \
  --output-file /tmp/supervisor-prompt.txt \
  --store-dir /tmp/globals --store-dir "session:/tmp/AUTO-IMP-SUP"

# Then launch the agent with the file via session_start.ts --prompt-file
```

This passes the rendered text directly — credentials are in the file and may be
corrupted if the agent re-passes them. Use only when the child can't use the vault.

## Cleanup

After a child agent finishes, clean up its prepared prompt and session data:

```bash
npx --yes tsx delete.ts --key prepared.prep-1776923319515-kks5ef --recursive \
  --store-dir /tmp/globals

# Optionally remove the session store directory entirely
rm -rf /tmp/AUTO-IMP-SUP
```
