Pi
Run Pi, the terminal coding agent, on Memtro as its model and add Memtro's memory and connector tools over MCP — with the :chat suffix that stops Pi's agent loop driving a second one.
Pi is a coding agent that runs in your terminal — a minimal agent harness from Earendil Works, with a TUI, a print mode, an RPC mode and an SDK. There are two ways to connect it to Memtro: install the extension, or write the config yourself. They do the same thing.
The quick way: the Memtro extension
export MEMTRO_API_KEY=sk-memtro-...
pi install git:github.com/memtro-org/pi-memtro
pi --model auto:chat
That is the whole setup. The extension registers both halves at once — Memtro as a model provider, and Memtro's MCP server for its tools — and discovers your organisation's actual model ladder from the API rather than asking you to keep a list in step by hand. Your key is read from the environment, never written into a config file.
Run /memtro in a session to check the connection: it reports the host, whether the key works, how many models it offers and where the tools are.
It is open source at memtro-org/pi-memtro — about 150 lines, worth reading before you install it, as with any Pi extension: they run inside the Pi process with your permissions.
Set MEMTRO_PI_TOOLS=0 if you want Memtro as the model and nothing else. MEMTRO_BASE_URL points it at a self-hosted Memtro.
Either way, read the next section — the model id is the part that matters.
Use auto:chat, not auto
This is the one thing to get right, and it applies to both routes.
Memtro answers in one of two modes. chat is a single reply. agent is a multi-step investigation that plans, calls tools across your connected systems and comes back when it has an answer. Which one a plain model id means is your organisation's default, set on Dashboard → Routing, and for a chat UI agent is often right.
Pi is not a chat UI. It runs an agent loop of its own — it reads files, runs commands and decides what to do next. So a default of agent puts Memtro's investigation inside Pi's loop, and every turn becomes an agent running an agent. That is not an error and nothing reports it. It is simply four minutes where there should have been four seconds, which is exactly how it was first found.
The :chat suffix is how a client with its own loop opts out. :agent forces the other way, for when you do want Memtro to go and investigate. The extension registers ids that already carry the suffix; if you are writing the config by hand, put it in yourself.
Or set it up by hand
Two independent pieces. Use either, or both.
1. Memtro as Pi's model
- Create a personal API key on Dashboard → Profile → API keys — it acts as you, with your memory, connections and permissions.
- Export it, so the config file does not hold the key:
export MEMTRO_API_KEY=sk-memtro-...
- Add Memtro to
~/.pi/agent/models.json(the user-level agent directory;PI_CODING_AGENT_DIRmoves it):
{
"$schema": "https://pi.dev/schemas/models.schema.json",
"providers": {
"memtro": {
"name": "Memtro",
"baseUrl": "https://platform.memtro.com/v1",
"api": "openai-completions",
"apiKey": "$MEMTRO_API_KEY",
"models": [
{ "id": "auto:chat", "name": "Memtro auto (one reply)", "reasoning": true, "contextWindow": 200000, "maxTokens": 32000 },
{ "id": "auto", "name": "Memtro auto (organisation default)", "reasoning": true, "contextWindow": 200000, "maxTokens": 32000 },
{ "id": "auto:agent", "name": "Memtro auto (multi-step agent)", "reasoning": true, "contextWindow": 200000, "maxTokens": 32000 }
]
}
}
}
- Start Pi on it:
pi --model auto:chat
Or press /model inside a session and pick it; /model re-reads models.json, so you do not need to restart Pi after editing the file.
Any id Memtro accepts works here: memtro for your default model, or a specific one such as anthropic/claude-opus-5, openai/gpt-5.4 or claude-code/opus, each with the same optional :chat / :agent suffix. Add them as further entries under models.
Memtro also speaks the Anthropic Messages API, if you would rather Pi used that wire: set "api": "anthropic-messages" and "baseUrl": "https://platform.memtro.com" — Anthropic clients append /v1/messages themselves.
2. Memtro's tools inside Pi (MCP)
Give Pi sessions Memtro's memory and your connected systems as tools, while Pi keeps whatever model it is already using.
pi mcp add memtro --url https://platform.memtro.com/api/mcp --bearer-token-env-var MEMTRO_API_KEY
pi mcp list
That writes a user-level server, available in every project. Add --local to write .pi/mcp.json for one project instead. The file form, in ~/.pi/agent/mcp.json:
{
"mcpServers": {
"memtro": {
"url": "https://platform.memtro.com/api/mcp",
"headers": { "Authorization": "Bearer ${MEMTRO_API_KEY}" },
"description": "Company memory, and the systems this organisation has connected"
}
}
}
Pi names MCP tools mcp__<server>__<tool>, so Memtro's arrive as mcp__memtro__memtro_search, mcp__memtro__memtro_remember, mcp__memtro__hubspot_search and so on — one per capability of every connection you have access to. Use /mcp inside a session to inspect, enable or disable them, and /reload after editing the file outside one.
The description line is worth keeping: Pi puts it in the system prompt and ranks the server's tools by it, so it is how the model knows what Memtro is for before it has called anything.
Try: "Use memtro to find who owns the billing migration and when it launches." or "Look up Help Scout ticket 2450 through memtro and check the customer in HubSpot."
Pi's own tools (files, bash) keep working throughout — Pi executes those itself and Memtro never sees them.
Thinking levels
Pi's thinking levels reach Memtro as reasoning_effort, which Memtro reads as two levels: low and medium ask for standard reasoning, high, xhigh and max ask for deep. The extension maps them already. By hand:
{
"id": "auto:chat",
"reasoning": true,
"thinkingLevelMap": { "low": "low", "medium": "medium", "high": "high", "xhigh": "xhigh", "max": "max" }
}
Memtro options from Pi
Anything in Memtro's memtro request field can be set per model, because Pi merges samplingParams into the request body and Memtro reads that field from the top level:
{
"id": "auto",
"name": "Memtro (chat, organisation memory)",
"samplingParams": { "memtro": { "mode": "chat", "memory": "org" } }
}
This is the long way round to what :chat does in one word, and it is the only way to reach the options that have no suffix — memory scope, the engine behind agent mode, and the rest of the API options. samplingParams applies to OpenAI-compatible APIs only.
Context windows and costs
Memtro's /v1/models reports model ids and nothing else — no context window, no output limit, no prices — and Pi needs all three. So the numbers above (and the extension's) are defaults chosen for the models Memtro usually routes to, not facts read from the endpoint. If yours differ, set them; the extension takes MEMTRO_CONTEXT_WINDOW and MEMTRO_MAX_TOKENS.
Costs are reported to Pi as zero on purpose. Memtro meters spend itself, per user and per team, on Usage; a second set of numbers in Pi's footer would only ever be the wrong ones.
Troubleshooting
- Every reply takes minutes: the model id has no
:chatand your organisation's default mode isagent, so Pi's loop is driving Memtro's. See Agent mode, or change the default on Dashboard → Routing. - 401 from the endpoint or the MCP server: the key is
sk-memtro-…and is shown once when created. For MCP the header must be exactlyAuthorization: Bearer sk-memtro-…;--bearer-token-env-varand the extension both write it for you. - No Memtro models in
/model: with the extension, run/memtro— noMEMTRO_API_KEYmeans the provider has no key to use and Pi leaves it out. By hand,models.jsonmust parse, and a provider that is not built in needs bothbaseUrland anapi. Opening/modelreloads the file. - No connector tools: connect the system on Dashboard → Connections first. MCP exposes only connections you or your organisation have, under the same per-tool grants as everywhere else.
- SSE errors: Memtro's MCP endpoint is Streamable HTTP at
/api/mcp. Pi rejects the legacy SSE transport, so do not set"type": "sse".