# Model Seam Report

Audience: AI coding agents first.

## 1. Pi model-id resolution

`resolve_model()` reads Pi's `pi --list-models` output, not `models.json` directly. It accepts an exact `provider/model-id`; otherwise it finds exact/suffix matches, then a sole substring match. Zero matches and multiple matches raise before spawn. `~/.pi/agent/models.json` is **not** the only registry: Pi's catalog merges built-in providers with custom models. `MODELS_JSON` is read directly only by `context_window()`, which first checks its `providers.<provider>.models[]`, then falls back to the CLI catalog. [agent_pi.py:43-64,67-90,108-117] [config.md:90-105]

## 2. Providers besides OpenRouter

Yes. Sources explicitly name these provider prefixes besides `openrouter`:

- `google`, selected by `defaults.model` or `agents[].model` as `google/<model-id>`; default is `google/gemini-3.6-flash`. [config.md:90-105] [sssf.config.yaml:3-6]
- `fireworks`, selected by `agents[].model` as `fireworks/accounts/fireworks/models/kimi-k3`. [sssf.config.yaml:39-42]
- `openai`, selected by `agents[].model` as `openai/gpt-5.6-terra` or `openai/gpt-5.6-luna`. [sssf.config.yaml:106-108,124-126]

The selection key is `model`: agent values inherit from `defaults`, and the leading segment is matched as the provider. [agents.py:33-41] [config.md:90-100] The supplied sources do not establish a complete Pi provider list; use `pi --list-models` for the live catalog. [agent_pi.py:43-64] [config.md:101-105]

## 3. Minimum `models.json` entry

**UNDETERMINED.** The supplied sources do not define Pi's `models.json` schema or its required fields. They prove only that this integration reads `providers.<provider>.models[]`, compares a model's `id`, and treats `contextWindow` as optional (`0` when absent). Model resolution itself is against `pi --list-models`. [agent_pi.py:108-117] [agent_pi.py:67-90]

## 4. OpenAI-compatible base URL and API key

**UNDETERMINED.** No supplied source defines generic OpenAI-compatible base-URL or API-key keys. This integration passes only provider and model to Pi, while preserving the operator environment; the config reference says credentials come from environment and gives `GEMINI_API_KEY` and `OPENROUTER_API_KEY` examples. It does not name a base-URL key or an OpenAI-compatible custom-provider schema. [agent_pi.py:217-246] [config.md:101-105]

## 5. Coding-agent adapter seam

Not swappable in v1. `agent_cc.py` is a stub that always raises, validation rejects every `coding_agent` except `pi`, and execution imports/calls `agent_pi` directly. [agent_cc.py:1-14] [agents.py:18-21,52-73,109-137]

A `cdx` adapter cannot work by configuration alone. After dispatch is refactored, it must satisfy this current call contract:

1. Accept request fields `prompt`, `system_prompt`, `model`, `thinking`, `session_id`, `session_dir`, `raw_output_path`, `tools`, `extensions`, and `cwd`; current runner constructs exactly that `PiRequest`. [data_types.py:371-385] [agents.py:112-126]
2. Provide `run(request, on_event=None, on_spawn=None, on_exit=None)` and return an object with `text`, `returncode`, `session_id`, `tokens`, `cost`, `usage`, `context_tokens`, and `context_window`; these fields feed parsing, accounting, persistence, and tracing. [agent_pi.py:208-286] [data_types.py:436-447] [agents.py:127-137,194-213]
3. Preserve resumable session semantics: retries reuse `session_id`; a changed model creates a new session. [agent_pi.py:217-225] [agents.py:221-232]
4. Either emit Pi-compatible tool events or replace `_event_forwarder`: it currently uses `ToolCallTracker`, which recognizes Pi `message_end`, `tool_execution_start`, and `tool_execution_end` events. [agent_pi.py:141-193] [agents.py:235-250]
5. Extend `coding_agent` accepted values, remove the Pi-only validation rule, and replace direct `agent_pi` references with adapter dispatch. [data_types.py:304-307,325-327] [agents.py:52-73,109-137]
