Connections
A connection is how Sigil reaches a model. Every model tier is a model name
(chatgpt-plan/<model>, claude-cc/opus, ollama_chat/qwen3:8b, openai/gpt-5), and
a name only works when a connection stands behind it.
Sigil cannot compile, chat or route without one, so setup requires a
connection. sigil setup does not finish until the frontier tier has a working
route.
sigil setup # connect a model (required), pick the tiers, set a persona
sigil connect <route> # connect one route directly
sigil connections # what is connected, and whether each tier can run
sigil disconnect <route> # sign out, or forget a key Sigil saved
The routes
| Route | sigil connect … |
How it connects | Who pays |
|---|---|---|---|
| ChatGPT | chatgpt |
Sign in with your browser | Your ChatGPT plan |
| Claude Code | claude-code |
The claude CLI's own sign-in |
Your Claude subscription |
| OpenRouter | openrouter |
Sign in with your browser; Sigil gets its own key | Your OpenRouter credits |
| Ollama | ollama [model] |
A local Ollama; ollama signin adds its :cloud models |
Nobody locally; your Ollama plan for :cloud |
| Ollama Cloud API | ollama-cloud |
Paste an ollama.com API key; no local Ollama needed | Your Ollama plan |
| OpenAI, Anthropic, Gemini, Z.ai | openai · anthropic · gemini · zai |
Paste an API key | That provider's API billing |
The first three need no API key.
ChatGPT: sign in, and your plan pays
sigil connect chatgpt
Sigil opens a ChatGPT sign-in in your browser. The first time, ChatGPT asks you
to approve Sigil and its use of your plan. Then the browser returns to Sigil
on a one-time loopback address (http://127.0.0.1:<port>/auth/callback), and the
connection is made.
This is OpenAI's Sign in with ChatGPT for open-source, locally hosted apps
(reference).
Sigil registers itself during that first sign-in, so there is no client secret
and no partner key. Each model call is one request to the public Responses API
(api.openai.com/v1/responses), counted against your ChatGPT plan:
- Usage and limits are managed in ChatGPT, at Settings → Usage. You can cap how much of your plan Sigil may use. On Plus, the five-hour limit is shared with every other app that uses your plan.
- Models are the ones your account lists. Sigil fetches that list when you
sign in.
chatgpt-plan/defaultmeans the first one, andsigil connectionsshows them all. - No CLI in the loop. A call is a direct API request, so there is no per-call preamble or process start like the Claude Code route has. That makes ChatGPT a reasonable small tier as well as a frontier.
- Signing out (
sigil disconnect chatgpt) revokes the session at OpenAI and deletes the tokens. It keeps the registration, so the next sign-in is one click. To use a different ChatGPT account, runsigil connect chatgpt --new. To remove Sigil from your account entirely, disconnect it in ChatGPT's settings.
Plan usage accepts only part of the Responses API: requests must use
store: false and stream: true, and cannot set sampling or output-budget
fields. Sigil binds these tiers the way it binds Claude Code tiers: tools and
output schemas travel as prose in the prompt (native_tools = false). Every
compiled slot works this way, and each request stays within what plan usage
accepts.
Set SIGIL_CHATGPT_EFFORT (low, medium or high) to pass a reasoning effort
with every call.
If a call's connection drops before the reply is complete (the computer slept,
the network went away, the server answered 429 or 5xx), Sigil sends the same
request again after 5, 15, 45 and 90 seconds, which covers the time a laptop's
network takes to come back after waking. A reply that goes silent for
SIGIL_CHATGPT_IDLE_S seconds (default 600) counts as dropped. A refused sign-in,
a usage limit or a bad request is never resent.
Claude Code: your Claude subscription
sigil connect claude-code # runs `claude auth login` if the CLI is not signed in
Each call is a headless claude -p run on your own subscription. Sigil does not
hold this login: it belongs to the claude CLI, so sigil disconnect leaves it
alone (claude auth logout signs it out everywhere). Costs, limits, and the
--claude flag that puts every tier on it for one run:
claude-code.
Every call carries Claude Code's own ~9k-token preamble, so this route fits the
frontier tier (compiling) much better than the small tier. Connecting it suggests
claude-cc/opus for the frontier and chat tiers and leaves the small tier on
something cheaper.
OpenRouter: one sign-in, many models
sigil connect openrouter
The browser opens OpenRouter's sign-in, you approve the key, and Sigil saves it
as OPENROUTER_API_KEY in the secrets file. Model names are
openrouter/<vendor>/<model>. Setup suggests openrouter/openrouter/auto,
OpenRouter's own router. Pin a specific model with sigil models set.
Ollama: on this machine
sigil connect ollama # status, and offers to pull qwen3:8b
sigil connect ollama qwen3:14b # pull a specific model
Sigil finds Ollama at 127.0.0.1:11434 (or $OLLAMA_HOST) and offers every
model you have pulled. For the small tier, setup picks a model of at least 7B
parameters, since smaller ones struggle to follow a compiled procedure.
Ollama's cloud models, through your local Ollama. Sign the local Ollama in to
ollama.com, and models with a :cloud tag run on Ollama's servers through the
same local API:
sigil connect ollama signin # runs `ollama signin`, which prints a link
sigil connect ollama glm-5.3:cloud # make it show up in Ollama's model list
The tier name is the ordinary local one (ollama_chat/glm-5.3:cloud). A :cloud
model needs no download, so Sigil does not require it to be pulled before a tier
can use it. When one is present, setup prefers it for the frontier tier, since it
is far stronger than anything that fits on a laptop.
Ollama Cloud API: no local Ollama
sigil connect ollama-cloud # paste a key from ollama.com/settings/keys
For a machine without Ollama installed, such as a server or CI. Tier names are
ollama-cloud/<model>, using the names on ollama.com's model list (glm-5.3,
gpt-oss:120b; no :cloud suffix). Setup suggests ollama-cloud/glm-5.3 for the
frontier and ollama-cloud/gpt-oss:20b for the small tier. The key is kept as
OLLAMA_API_KEY in the secrets file.
Sigil gives the https://ollama.com base to these tiers only. It deliberately
does not set OLLAMA_API_BASE, because litellm applies that variable to every
Ollama call and would send your local tiers to the cloud as well.
API keys
sigil connect openai # prompts for the key, hidden; then tests it
sigil connect anthropic sk-ant-… # or pass it inline
The key goes into $SIGIL_HOME/secrets.env (0600, readable by you alone) and
never onto the graph. A key exported in your shell always wins over the file.
The Observatory's Keys & secrets page manages the same file.
Web search
These connections are not model routes. They are what the agent's web_search
tool runs on, and they never take a tier or count toward the setup requirement.
sigil connect tavily # browser sign-ins, no API key
sigil connect exa
sigil connect parallel
sigil connect perplexity
sigil connect serper # paste a Serper key (Google results)
| Provider | How | Notes |
|---|---|---|
| Tavily | sign-in | Free plan: 1,000 searches a month. Uses one of your Tavily API keys behind the scenes. |
| Exa | sign-in | Also works with no account, at low limits. Signing in raises them. |
| Parallel | sign-in | Search built for AI agents. The sign-in issues a long-lived key, with no refresh. |
| Perplexity | sign-in | Billed to your Perplexity API account. Perplexity does not document this sign-in, so it may change. |
| Serper | key | Google results. Get a key at serper.dev. |
The four sign-ins connect the way ChatGPT does: a link, a sign-in, and it works.
The browser comes back to a one-time loopback address
(http://127.0.0.1:<port>/callback). Each sign-in goes through the provider's
hosted MCP server, using the MCP authorization spec:
- Sigil reads the server's OAuth metadata.
- Sigil registers itself as a public client during that first sign-in, with no secret (RFC 7591 dynamic client registration).
- The sign-in uses PKCE. Its token is good for that MCP server only, and each search is an MCP tool call.
Sigil checks the token with the server, and saves the search tool's input
schema, before it says "connected". Search tools differ in shape: Exa wants a
query and an objective, and Parallel a list of search_queries. Sigil
builds the arguments from that saved schema. sigil disconnect <provider>
revokes the session where the provider allows it, and deletes the token.
Two more routes need no search connection at all:
- ChatGPT. When a model tier runs on your ChatGPT plan,
web_searchuses ChatGPT's own hosted web search. Each search is one request against your plan, and its answer cites its sources.SIGIL_CHATGPT_SEARCH=0turns this off. - Exa with no account. This is the last resort, so a fresh install can
still search. It is rate-limited.
SIGIL_KEYLESS_SEARCH=0turns it off.
Serper has no sign-in, only a key from serper.dev,
kept in secrets.env like any other.
web_search tries these routes in order:
- a signed-in provider
- the Brave, Serper and Firecrawl keys
- ChatGPT's search, when a tier runs on your plan
- Claude Code's WebSearch, in claude mode
- Exa with no account
See models.
Tiers, from what is connected
After you connect, setup suggests a model for each tier:
| Tier | Prefers, in order |
|---|---|
frontier, chat |
ChatGPT, Claude Code, Anthropic, OpenAI, OpenRouter, Gemini, Z.ai, Ollama |
small, router |
Ollama (≥7B), ChatGPT, OpenAI, Anthropic, Gemini, OpenRouter, Z.ai, Claude Code |
Subscriptions come first for the frontier, because compiling is rare and
judgment-heavy. Local and cheap routes come first for the small tier, which runs
every compiled skill. Accept the suggestion, edit any tier, or change one later
with sigil models set <tier> <name>. sigil connect <route> on its own also
offers to point the tiers at the route you just connected.
The first-run gate
chat, compile, solve, relearn and eval check first that the frontier
and chat tiers have a live route. On a terminal, when they do not, the command
goes through setup first. Piped or scripted, it prints one warning and carries
on, so CI and other automation still run. --claude runs skip the gate, because
--claude checks the Claude Code login itself.
SIGIL_REQUIRE_CONNECTION=0 turns the gate off.
The check makes no model calls. It looks at the credentials on disk, the environment, and the local Ollama port.
In chat
Chat uses the same word for the same thing:
| Command | What it does |
|---|---|
/connect |
What is connected, and whether each tier can run |
/connect <provider> |
The same flow as sigil connect <provider>: a browser sign-in, or a key asked for without echo. The full-screen chat hands the terminal over while it runs, then returns |
/connections |
The status table on its own |
/channel <kind> |
Setup steps for a messaging channel (Discord, Telegram, WhatsApp, Slack). /connect discord still answers, and points here |
Or ask in plain words ("connect my ChatGPT", "which models are set up?"). The agent has
model_connections, connect_model and use_model_provider. connect_model opens a
browser sign-in on this machine for ChatGPT and OpenRouter. It never takes an API key:
anything typed into chat is sent to the model and kept in the transcript, so for a key
provider it tells you to run /connect <provider>. In the Observatory's chat or a
channel conversation, it points to the Model providers page instead, because those
conversations run in a process that ends before a browser sign-in could finish.
In the Observatory
Settings → Model providers (Settings is in the top bar, and the page is also a tile on the Dashboard) lists every route with its status, and a row for each tier showing whether it can run:
- Continue with ChatGPT and Sign in to OpenRouter open the sign-in in a new tab. The page waits until you finish, then offers to point the tiers at the new connection.
- Add key saves and tests a key in one step.
- Use for tiers points the tiers at a connected route.
- Claude Code and Ollama show the one command to run in a terminal, and a Check again button.
While nothing is connected, every page shows a banner linking there.
The browser sign-ins return to a loopback address on the machine running Sigil, so they work when the Observatory and your browser are on the same machine. For a remote Sigil, connect from its terminal instead.
Where credentials live
| What | Where |
|---|---|
| ChatGPT sign-in | $SIGIL_HOME/auth/chatgpt.json (0600) |
| This machine's ChatGPT host id | $SIGIL_HOME/auth/host_id: an opaque urn:uuid:…, not a credential |
| OpenRouter and API keys | $SIGIL_HOME/secrets.env (0600) |
| Search sign-ins | $SIGIL_HOME/auth/search-<provider>.json (0600), refreshed under a lock like ChatGPT's |
| Claude Code | the claude CLI's own config; Sigil only reads which account it is |
None of them is ever written to the graph or to jac.toml. The ChatGPT access
token lasts an hour and is refreshed automatically. The CLI, the daemon and every
compiled-skill run share the one file, and they refresh under a lock: refresh
tokens rotate, and two processes racing to use the same one would sign you out.
Ejected runnables
sigil compile -e agent.jac produces a standalone file with no Sigil imports, so
there is no Sigil code in it to sign in with ChatGPT or drive Claude Code. Give an
ejected program a normal provider name (SIGIL_MODEL=openai/gpt-5,
ollama_chat/…).
Troubleshooting
| Symptom | Fix |
|---|---|
Sigil needs a model connection first |
Finish sigil setup, or sigil connect <route> |
| No browser opened | Open the link Sigil prints, on the same machine. Over SSH, connect a route that needs no browser, or forward the port it prints |
the sign-in was declined in the browser |
Run sigil connect chatgpt again and approve Sigil |
signed in, but plan use was not allowed |
Run sigil connect chatgpt again and allow Sigil to use your plan |
your ChatGPT plan's usage limit for Sigil is reached |
Wait, or raise Sigil's limit at chatgpt.com/settings/usage |
the ChatGPT sign-in has expired |
sigil connect chatgpt: one click, since the registration is kept |
that model is not offered to this ChatGPT account |
sigil connections lists the account's models |
Ollama has not pulled … |
sigil connect ollama <model> |
A :cloud model fails with an auth error |
The local Ollama is not signed in: sigil connect ollama signin |
A tier shows ✗ in sigil connections |
The reason is on the same line. sigil setup re-suggests tiers from what is connected |
Environment
| Variable | Default | What it does |
|---|---|---|
SIGIL_REQUIRE_CONNECTION |
on | 0 turns off the first-run gate |
SIGIL_CHATGPT_EFFORT |
unset | reasoning effort sent with every ChatGPT call |
SIGIL_CHATGPT_RESENDS |
4 |
how many times a dropped ChatGPT call is sent again (0 = never) |
SIGIL_CHATGPT_IDLE_S |
600 |
seconds of silence before a ChatGPT reply counts as dropped (0 = wait forever) |
OLLAMA_HOST |
127.0.0.1:11434 |
where Sigil looks for Ollama |
OLLAMA_API_KEY |
unset | the Ollama Cloud API key (sigil connect ollama-cloud saves it) |
SIGIL_CLAUDE_BIN |
claude |
the Claude Code binary |
See also
- models: the tiers, aliases and fallback chains
- claude-code: the Claude Code route in depth, and serving skills back to it