# Goose runtime

Ouroboros can run orchestrator workers through the Goose CLI with `runtime_backend: goose`.

The Goose runtime uses the headless Goose task interface documented by Goose:

```bash
goose run --output-format stream-json -i -
```

Ouroboros writes the composed worker prompt to stdin, consumes `stream-json` events, and normalizes them into the shared runtime message model used by the orchestrator.

## Configuration

Set the runtime backend and, optionally, an explicit Goose CLI path:

```yaml
orchestrator:
  runtime_backend: goose
  goose_cli_path: /path/to/goose
```

To route Ouroboros LLM-only calls (interviews, evaluation, consensus, seed generation) through Goose as well, set:

```yaml
llm:
  backend: goose
```

You can also use the environment variable:

```bash
OUROBOROS_GOOSE_CLI_PATH=/path/to/goose
```

If no path is configured, Ouroboros resolves `goose` from `PATH` at runtime.

## Setup

If `goose` is on `PATH`, configure Ouroboros with:

```bash
ouroboros setup --runtime goose
```

Or switch an existing config with:

```bash
ouroboros config backend goose
```

## MCP server

The MCP server accepts Goose as an orchestrator runtime and LLM backend:

```bash
ouroboros mcp serve --runtime goose --llm-backend goose
```

## Nested Goose/Ouroboros safety

When Ouroboros launches Goose as a child runtime, it sets `_OUROBOROS_NESTED=1` and strips Ouroboros runtime-selection environment variables from the child process. This is intended to prevent accidental Ouroboros-in-Goose-in-Ouroboros recursion when the parent session is itself running inside Goose.

For best results, ensure child Goose sessions do not auto-load an Ouroboros MCP extension unless you intentionally want nested orchestration.

## Capabilities

The current runtime declares:

- `skill_dispatch=True`
- `targeted_resume=True`
- `structured_output=True`

Resume is implemented using stable Goose session names generated by Ouroboros and passed to `goose run -n <name> --resume` on subsequent invocations.

## Experimental status and limitations

Goose support is implemented as an experimental CLI backend. It intentionally does not claim full parity with Claude Code or Codex CLI backends:

- Tool restrictions are soft-enforced through prompt guidance and post-hoc event auditing. Goose CLI does not currently expose the same hard tool allowlist/sandbox surface.
- Structured completion output is cooperative. Ouroboros injects strict JSON/schema instructions and extracts valid JSON from Goose output, but Goose CLI has no Codex-style `--output-schema` hard-enforcement flag.
- Runtime resume uses Ouroboros-generated Goose session names. This provides deterministic targeted resume for Ouroboros workers, but depends on Goose CLI session-name behavior.
- Nested Ouroboros-in-Goose recursion is guarded by environment cleanup and `_OUROBOROS_NESTED=1`; users should still avoid auto-loading an Ouroboros MCP extension in child Goose sessions unless nested orchestration is intentional.

## Notes

This runtime depends on the Goose CLI `run` command and `--output-format stream-json` support. Goose Desktop's bundled `goosed` server binary is not the same interface as the `goose` CLI used here.


## LLM backend support

`llm.backend: goose` uses `goose run --output-format stream-json --no-session -i -` for completion-style calls. It shares the same `goose_cli_path`/`OUROBOROS_GOOSE_CLI_PATH` resolution as the runtime backend.

Structured `response_format` requests are enforced cooperatively: Ouroboros injects a strict JSON/schema instruction and extracts valid JSON from Goose output. Goose CLI currently has no Codex-style `--output-schema` hard-enforcement flag, so malformed structured responses may be retried and then surfaced as provider errors.
