# Guide for coding agents

> How an AI coding agent should integrate a product with Switchboard without inventing provider-key wiring.

## Discovery order (follow this)

1. Fetch **`/llms.txt`** (site root) or read `docs/llms.txt` in-repo — curated index, keep it in context.
2. Load **`/openapi.yaml`** (or `docs/openapi.yaml`) for exact paths, params, and schemas.
3. Open only the linked Markdown pages you need (prefer `.md` URLs under `/docs/…`).
4. If you need everything in one shot, use **`/llms-full.txt`** — last resort; it is large.

Do **not** scrape marketing HTML for API contracts. Do **not** invent OpenAI-compat as the default multi-provider path.

## Integration checklist

1. Confirm the product will hold **only** `SB_KEY` + `SWITCHBOARD_BASE_URL` (no provider secrets in app env when hub-owned).
2. Pick a mode from [call-modes.md](./call-modes.md):
   - Product AI → thinking tiers (`anybody` / `thinker` / `expert`)
   - Existing vendor AI SDKs → proxy + `createProxyFetch`
   - Payments/SMS/CRM/social → `/v1/call/{connector}.{op}`
   - Agent runtime → `POST /v1/mcp`
3. Tell the human/operator to mint a key with the right connector scopes and publish LKG (you cannot invent a production key).
4. Wire TypeScript via [sdk-typescript.md](./sdk-typescript.md) when the stack is TS; otherwise raw HTTP per OpenAPI.
5. Always send `Idempotency-Key` on side-effect ops.
6. Parse envelopes correctly: success → use `data`; failure → `error` with `data: null`.
7. For proxy `baseURL`, never double `/v1` — see call-modes table.

## Forbidden patterns

- Putting `OPENAI_API_KEY` / `STRIPE_SECRET_KEY` / etc. in the app when Switchboard owns the hop
- Pointing Anthropic or Google SDKs at `{cell}/v1/chat/completions`
- Setting `baseURL` to `{cell}/v1/proxy/anthropic/v1` (double prefix)
- Treating any JSON with `meta` as success without checking `error`
- Retrying `403 forbidden_scope` or `401` in a loop
- Calling admin (`/v1/admin/…`) with a product caller key

## Base URL

Use your cell hostname in production and staging:

```text
https://{cell}   # e.g. https://us1.switchboard.example
```

Set `SWITCHBOARD_BASE_URL` to that value. Do **not** hard-code `http://127.0.0.1:8080` in product code — that only works when you are running the local gateway.

## Local verification commands

From repo `platform/` (when developing against a local cell):

```bash
make run-sim          # terminal 1 — fake provider
make run-gateway      # terminal 2 — cell on http://127.0.0.1:8080
# Live smoke: sb_live_app_<slug>_<secret>
# Sandbox (no live spend): sb_test_app_sandbox_devsecret01
export SWITCHBOARD_BASE_URL=http://127.0.0.1:8080
export SB_KEY=sb_test_app_sandbox_devsecret01
```

Smoke a tier call (set `SWITCHBOARD_BASE_URL` and `SB_KEY` from your cell):

```bash
curl -sS "$SWITCHBOARD_BASE_URL/v1/proxy/switchboard/chat/completions" \
  -H "Authorization: Bearer $SB_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"anybody","messages":[{"role":"user","content":"ping"}],"max_tokens":16}'
```


## MCP vs docs MCP

- **Switchboard MCP** (`POST /v1/mcp` on a cell) = runtime tools for *product* agents using a Switchboard key.
- **These docs** (`llms.txt` + OpenAPI + Markdown) = how *coding* agents should write integration code.

They are complementary. A coding agent reads docs; a product agent calls cell MCP.

## Source of truth

| Artifact | Role |
|---|---|
| `docs/openapi.yaml` | HTTP contract for callers |
| `docs/*.md` | Human + agent prose |
| `platform/schemas/envelope.schema.json` | Envelope JSON Schema |
| `platform/connectors/*/connector.yaml` | Per-provider ops (hub-native) |
| `sdk/typescript/` | Official TS client |

When docs and code disagree, prefer OpenAPI + connector YAML + envelope schema, then file a docs fix.
