Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Added

- **OrcaRouter as a named model provider** — `orcarouter/auto` (smart-routing gateway from [OrcaRouter](https://www.orcarouter.ai)) is now part of the auto-selection preference list in `agent_config.ts`, so the plugin picks it up automatically when the Letta server exposes an `orcarouter` provider. Set `LETTA_MODEL="orcarouter/auto"` to opt in directly.

### Fixed

- **Deprecated `llm_config` PATCH shape** — `updateAgentModel()` was sending `{ llm_config: {...} }` as the agent PATCH body. Letta now rejects that with HTTP 400 ("The `llm_config` field is deprecated and no longer accepted. Use the `model` field instead."). The session-start model/context-window sync therefore failed silently on every Claude Code launch, leaving `LETTA_MODEL` / `LETTA_CONTEXT_WINDOW` env overrides un-applied — agents stayed pinned to whatever they last had server-side. Switched to the new top-level `model` + `context_window_limit` shape.
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ When the agent's model isn't available, the plugin selects from available models
6. `google_ai/gemini-3-flash` (Google's balanced option)
7. `google_ai/gemini-2.5-flash` (fallback)
8. `minimax/MiniMax-M2.7` (MiniMax flagship, 1M context)
9. First available model on the server
9. `orcarouter/auto` (OrcaRouter smart-routing gateway)
10. First available model on the server

#### Manual Override

Expand All @@ -212,6 +213,7 @@ The model handle format is `provider/model`. Common options:
| `anthropic` | `claude-sonnet-4-5`, `claude-opus-4-5`, `claude-haiku-4-5` |
| `google_ai` | `gemini-3-flash`, `gemini-2.5-flash`, `gemini-2.5-pro` |
| `minimax` | `MiniMax-M2.7` (1M context) |
| `orcarouter` | `auto` (OrcaRouter smart-routing gateway) |
| `zai` | `glm-5` (Letta Cloud default, free) |

If `LETTA_MODEL` is set but not available on the server, the plugin will warn you and fall back to auto-selection.
Expand All @@ -220,6 +222,18 @@ The default bundled agent uses `zai/glm-5` (free on Letta Cloud). For better too

**Note:** Ensure your Letta server has the appropriate API key configured for your chosen provider (e.g., `OPENAI_API_KEY` for OpenAI models).

#### Using OrcaRouter as your model gateway

[OrcaRouter](https://www.orcarouter.ai) is a unified AI gateway that routes every request to the best model for the job — one API key, one endpoint, all providers. It also runs gateway-level, zero-trust security for AI agents on the same endpoint — screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes.

If your Letta server exposes an OrcaRouter provider (`provider_type: orcarouter`), point Subconscious at it with the `orcarouter/auto` smart-routing handle:

```bash
export LETTA_MODEL="orcarouter/auto"
```

`auto` routes each request to the most suitable upstream model automatically, so you get strong reasoning and tool use without pinning to a specific model. Like any other provider, the plugin auto-selects `orcarouter/auto` from the available-models list when it's present and the configured model isn't. To use OrcaRouter with a self-hosted Letta server, configure the server's `ORCAROUTER_API_KEY` alongside its base URL, then set `LETTA_BASE_URL` to that server.

## Default Subconscious Agent

When no agent is configured, the plugin auto-imports a bundled "Subconscious" agent designed specifically for this use case.
Expand Down
15 changes: 15 additions & 0 deletions scripts/agent_config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const SAMPLE_MODELS = [
{ model: 'gemini-3-pro-preview', name: 'gemini-3-pro-preview', provider_type: 'google_ai', handle: 'google_ai/gemini-3-pro-preview' },
{ model: 'gemini-3-pro-preview', name: 'gemini-3-pro-preview', provider_type: 'google_ai', handle: 'gem1/gemini-3-pro-preview' },
{ model: 'gpt-5.2', name: 'gpt-5.2', provider_type: 'openai', handle: 'openai/gpt-5.2' },
{ model: 'auto', name: 'auto', provider_type: 'orcarouter', handle: 'orcarouter/auto' },
];

describe('findModel', () => {
Expand All @@ -132,6 +133,12 @@ describe('findModel', () => {
expect(result!.provider_type).toBe('openai');
});

it('should find an OrcaRouter gateway model by handle', () => {
const result = findModel(SAMPLE_MODELS, 'orcarouter/auto');
expect(result).not.toBeNull();
expect(result!.handle).toBe('orcarouter/auto');
});

it('should return null for unknown model', () => {
expect(findModel(SAMPLE_MODELS, 'unknown/model')).toBeNull();
});
Expand Down Expand Up @@ -194,4 +201,12 @@ describe('buildLlmConfig', () => {
expect(config.handle).toBe('openai/gpt-5.2');
expect(config.provider_name).toBe('openai');
});

it('should split an OrcaRouter model handle into provider and model', () => {
const config = buildLlmConfig('orcarouter/auto', SAMPLE_MODELS, undefined);
expect(config.model).toBe('auto');
expect(config.handle).toBe('orcarouter/auto');
expect(config.provider_name).toBe('orcarouter');
expect(config.model_endpoint_type).toBe('orcarouter');
});
});
1 change: 1 addition & 0 deletions scripts/agent_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const PREFERRED_MODELS = [
'google_ai/gemini-3-flash', // Google's balanced option
'google_ai/gemini-2.5-flash', // Fallback
'minimax/MiniMax-M2.7', // MiniMax flagship, 1M context
'orcarouter/auto', // OrcaRouter smart-routing gateway (https://www.orcarouter.ai)
];

interface Config {
Expand Down