Headless Runs

On this page 6

buddy run executes a prompt as a pipeline step and, optionally, enforces a schema on the output so later steps can consume it safely.

buddy run --prompt "Summarize this week's dependency updates as release notes"

The result goes to stdout. Inside GitHub Actions it is also written to $GITHUB_OUTPUT as result.

Schema-validated output

buddy run \
  --prompt "Summarize the dependency changes merged this week" \
  --output-schema '{
    "type": "object",
    "properties": { "markdown": { "type": "string" } },
    "required": ["markdown"]
  }'

When a schema is given, output that does not conform fails the command (exit ≠ 0). That is the whole point of the flag. A later step doing fromJSON(steps.x.outputs.result).markdown needs this step to have failed rather than to have emitted something shaped differently than it promised — otherwise the mistake surfaces three steps downstream as a confusing error, or worse, as an empty string that silently publishes.

Before failing, Buddy re-asks with the specific violations quoted back:

- markdown: is required but missing

That usually succeeds, and burning the step on a formatting slip would be needless. --retries controls how many times (default 2).

Supported schema subset

type, required, properties, items, enum.

Deliberately partial — that is what a pipeline step's schema realistically declares. Supporting more would mean either a dependency or a half-correct validator that passes things it should not, which is worse than a small one that is right about what it covers.

In a workflow

- uses: stacksjs/buddy/action@v1
  id: notes
  with:
    prompt: Summarize the dependency changes merged this week as release notes.
    output-schema: '{"type":"object","properties":{"markdown":{"type":"string"}},"required":["markdown"]}'
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

- run: echo '${{ fromJSON(steps.notes.outputs.result).markdown }}'

The action is a thin wrapper over the CLI — bunx @buddysh/buddy run in any step does the same thing.

Output escaping

Multi-line values are written to $GITHUB_OUTPUT using heredoc syntax with a delimiter chosen to be absent from the value. This matters: if a value could contain the delimiter, crafted output could close the block early and inject further outputs into the workflow, which is a real escalation once a later step interpolates them.

Prompt safety

Pass prompts through --prompt-file or the action's prompt input rather than interpolating them into a shell command. If a prompt is built from a pull request title, an issue body, or a comment, that content is attacker-controlled — interpolating it into a run: block directly would be a command injection regardless of which tool consumes it.

Options

FlagDescription
--prompt <text>The prompt to run
--prompt-file <path>Read the prompt from a file
--output-schema <json>JSON Schema the output must satisfy
--output-schema-fileRead the schema from a file
--model <name>Model override
--retries <n>Schema retries before failing (default 2)
--verboseLog diagnostics to stderr

Diagnostics always go to stderr; stdout carries only the result.

Suggest a change to this page

Last updated: