-
Notifications
You must be signed in to change notification settings - Fork 196
docs(rfd): Сustom LLM endpoints #648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
xtmq
wants to merge
14
commits into
agentclientprotocol:main
Choose a base branch
from
xtmq:evgeniy.stepanov/rfd-custom-url
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+386
−0
Open
Changes from 4 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
98a7a30
Add custom-llm-endpoint.mdx
anna239 8c26ce7
make authHeader optional
anna239 6b8332f
support for multiple providers
anna239 42ddd4c
docs: revise custom LLM endpoint RFD to use dedicated setLlmEndpoints…
xtmq f7548d9
docs: update custom LLM endpoint RFD to include provider-based capabi…
xtmq a9c4fad
docs: update custom LLM endpoint RFD - wording
xtmq 4091d1d
docs: rename llm provider to llm protocol in custom LLM endpoint RFD
xtmq d5fbf96
docs: make LlmProtocol an open string type with well-known values in …
xtmq 09a8de0
docs: resolve model availability open question in custom LLM endpoint…
xtmq fd3aa2c
docs: update revision history in custom LLM endpoint RFD
xtmq 8e93892
docs: formatting for custom LLM endpoint RFD
xtmq 5eec689
docs(rfd): redesign custom LLM endpoint proposal into providers list/…
xtmq c2a9777
docs(rfd): finalized provider disable semantics
xtmq b6cf319
docs(rfd): add FAQ on why providers/* is preferred over session-config
xtmq File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,293 @@ | ||
| --- | ||
| title: "Custom LLM Endpoint Configuration" | ||
| --- | ||
|
|
||
| - Author(s): [@anna239](https://github.com/anna239), [@xtmq](https://github.com/xtmq) | ||
|
|
||
| > **Note:** This RFD is very preliminary and intended to start a dialog about this feature. The proposed design may change significantly based on feedback and further discussion. | ||
|
|
||
| ## Elevator pitch | ||
|
|
||
| > What are you proposing to change? | ||
|
|
||
| Add the ability for clients to pass custom LLM endpoint URLs and authentication credentials to agents via a dedicated `setLlmEndpoints` method, with support for multiple providers. This allows clients to route LLM requests through their own infrastructure (proxies, gateways, or self-hosted models) without agents needing to know about this configuration in advance. | ||
|
|
||
| ## Status quo | ||
|
|
||
| > How do things work today and what problems does this cause? Why would we change things? | ||
|
|
||
| Currently, agents are configured with their own LLM endpoints and credentials, typically through environment variables or configuration files. This creates problems for: | ||
|
|
||
| - **Client proxies**: Clients want to route agent traffic through their own proxies, f.i. for setting additional headers or logging | ||
| - **Enterprise deployments**: Organizations want to route LLM traffic through their own proxies for compliance, logging, or cost management | ||
| - **Self-hosted models**: Users running local LLM servers (vLLM, Ollama, etc.) cannot easily redirect agent traffic | ||
| - **API gateways**: Organizations using LLM gateways for rate limiting, caching, or multi-provider routing | ||
|
|
||
| ## Shiny future | ||
|
|
||
| > How will things play out once this feature exists? | ||
|
|
||
| Clients will be able to: | ||
| 1. Discover whether an agent supports custom LLM endpoints via capabilities during initialization | ||
| 2. Perform agent configuration, including authorization based on this knowledge | ||
| 3. Pass custom LLM endpoint URLs and headers for different providers via a dedicated method | ||
| 4. Have agent LLM requests automatically routed through the appropriate endpoint based on provider | ||
|
|
||
| ## Implementation details and plan | ||
|
|
||
| > Tell me more about your implementation. What is your detailed implementation plan? | ||
|
|
||
| ### Intended flow | ||
|
|
||
| The design uses a two-step approach: capability discovery during initialization, followed by endpoint configuration via a dedicated method. This enables the following flow: | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| participant Client | ||
| participant Agent | ||
|
|
||
| Client->>Agent: initialize | ||
| Note right of Agent: Agent reports capabilities,<br/>including llmEndpoints support | ||
| Agent-->>Client: initialize response<br/>(agentCapabilities.llmEndpoints = true) | ||
|
|
||
| Note over Client: Client sees llmEndpoints capability.<br/>Performs configuration / authorization<br/>based on this knowledge. | ||
|
|
||
| Client->>Agent: setLlmEndpoints | ||
| Agent-->>Client: setLlmEndpoints response<br/>(accepted providers) | ||
|
|
||
| Note over Client,Agent: Ready for session setup | ||
| Client->>Agent: session/new | ||
| ``` | ||
|
|
||
| 1. **Initialization**: The client calls `initialize`. The agent responds with its capabilities, including an `llmEndpoints` flag indicating support for custom endpoint configuration. | ||
| 2. **Client-side decision**: The client inspects the capability. If the agent supports `llmEndpoints`, the client can perform authorization, resolve credentials, or configure endpoints accordingly. If the agent does not support it, the client falls back to a different authorization and configuration strategy. | ||
| 3. **Endpoint configuration**: The client calls `setLlmEndpoints` with provider-to-endpoint mappings. The agent responds with the subset of providers it accepted. | ||
| 4. **Session creation**: The client proceeds to create a session. | ||
|
|
||
| ### Capability advertisement | ||
|
|
||
| The agent advertises support for custom LLM endpoints via a new capability flag in `agentCapabilities`: | ||
|
|
||
| ```typescript | ||
| interface AgentCapabilities { | ||
| // ... existing fields ... | ||
|
|
||
| /** Whether the agent supports custom LLM endpoint configuration via setLlmEndpoints */ | ||
| llmEndpoints?: boolean; | ||
| } | ||
| ``` | ||
|
|
||
| **Initialize Response example:** | ||
| ```json | ||
| { | ||
| "jsonrpc": "2.0", | ||
| "id": 0, | ||
| "result": { | ||
| "protocolVersion": 1, | ||
| "agentInfo": { | ||
| "name": "MyAgent", | ||
| "version": "2.0.0" | ||
| }, | ||
| "agentCapabilities": { | ||
| "llmEndpoints": true, | ||
| "sessionCapabilities": {} | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### `setLlmEndpoints` method | ||
|
|
||
| A dedicated method that can be called after initialization but before session creation. | ||
|
|
||
| ```typescript | ||
| /** Well-known LLM provider identifiers */ | ||
| type LlmProvider = "anthropic" | "openai" | "google" | "amazon" | "will be added later"; | ||
|
|
||
| interface LlmEndpointConfig { | ||
| /** Base URL for LLM API requests (e.g., "https://llm-proxy.corp.example.com/v1") */ | ||
| url: string; | ||
|
|
||
| /** | ||
| * Additional HTTP headers to include in LLM API requests. | ||
| * Each entry is a header name mapped to its value. | ||
| * Common use cases include Authorization, custom routing, or tracing headers. | ||
| */ | ||
| headers?: Record<string, string> | null; | ||
|
|
||
| /** Extension metadata */ | ||
| _meta?: Record<string, unknown>; | ||
| } | ||
|
|
||
| interface SetLlmEndpointsRequest { | ||
| /** | ||
| * Custom LLM endpoint configurations per provider. | ||
| * When provided, the agent should route LLM requests to the appropriate endpoint | ||
| * based on the provider being used. | ||
| * This configuration is per-process and should not be persisted to disk. | ||
| */ | ||
| endpoints: Record<LlmProvider, LlmEndpointConfig>; | ||
xtmq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /** Extension metadata */ | ||
| _meta?: Record<string, unknown>; | ||
| } | ||
|
|
||
| interface SetLlmEndpointsResponse { | ||
| /** | ||
| * Echoed back with the providers the agent accepts. | ||
| * Only includes providers that the agent will actually use. | ||
| * If empty, the agent did not accept any endpoints. | ||
| */ | ||
| accepted: Record<LlmProvider, LlmEndpointConfig>; | ||
|
|
||
| /** Extension metadata */ | ||
| _meta?: Record<string, unknown>; | ||
| } | ||
| ``` | ||
|
|
||
| #### JSON Schema Additions | ||
|
|
||
| ```json | ||
| { | ||
| "$defs": { | ||
| "LlmEndpointConfig": { | ||
| "description": "Configuration for a custom LLM endpoint.", | ||
| "properties": { | ||
| "url": { | ||
| "type": "string", | ||
| "description": "Base URL for LLM API requests." | ||
| }, | ||
| "headers": { | ||
| "type": ["object", "null"], | ||
| "description": "Additional HTTP headers to include in LLM API requests.", | ||
| "additionalProperties": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "_meta": { | ||
| "additionalProperties": true, | ||
| "type": ["object", "null"] | ||
| } | ||
| }, | ||
| "required": ["url"], | ||
| "type": "object" | ||
| }, | ||
| "LlmEndpoints": { | ||
| "description": "Map of provider identifiers to endpoint configurations. This configuration is per-process and should not be persisted to disk.", | ||
| "type": "object", | ||
| "additionalProperties": { | ||
| "$ref": "#/$defs/LlmEndpointConfig" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| #### Example Exchange | ||
|
|
||
| **setLlmEndpoints Request:** | ||
| ```json | ||
| { | ||
| "jsonrpc": "2.0", | ||
| "id": 2, | ||
| "method": "setLlmEndpoints", | ||
| "params": { | ||
| "endpoints": { | ||
| "anthropic": { | ||
| "url": "https://llm-gateway.corp.example.com/anthropic/v1", | ||
| "headers": { | ||
| "Authorization": "Bearer anthropic-token-abc123", | ||
| "X-Request-Source": "my-ide" | ||
| } | ||
| }, | ||
| "openai": { | ||
| "url": "https://llm-gateway.corp.example.com/openai/v1", | ||
| "headers": { | ||
| "Authorization": "Bearer openai-token-xyz789" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| **setLlmEndpoints Response:** | ||
| ```json | ||
| { | ||
| "jsonrpc": "2.0", | ||
| "id": 2, | ||
| "result": { | ||
| "accepted": { | ||
| "anthropic": { | ||
| "url": "https://llm-gateway.corp.example.com/anthropic/v1", | ||
| "headers": { | ||
| "Authorization": "Bearer anthropic-token-abc123", | ||
| "X-Request-Source": "my-ide" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| In this example, the agent only uses Anthropic, so it only accepts that provider's configuration. | ||
|
|
||
| #### Behavior | ||
|
|
||
| 1. **Capability discovery**: The agent MUST advertise `llmEndpoints: true` in `agentCapabilities` if it supports the `setLlmEndpoints` method. Clients SHOULD check this capability before calling the method. | ||
|
|
||
| 2. **Timing**: The `setLlmEndpoints` method MUST be called after `initialize` and before `session/new`. Calling it during an active session is undefined behavior. All subsequent sessions will use the newly configured endpoints. | ||
xtmq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| 3. **Confirmation via response**: The agent MUST respond with the `accepted` map containing only the providers it will actually use. If the agent accepts none, the `accepted` map SHOULD be empty. | ||
|
|
||
| 4. **Per-process scope**: The endpoint configuration applies to the entire agent process lifetime. It should not be stored to disk or persist beyond the process. | ||
|
|
||
| 5. **Provider-based routing**: The agent should route LLM requests to the appropriate endpoint based on the provider. If the agent uses a provider not in the provided map, it uses its default endpoint for that provider. | ||
|
|
||
| 6. **Agent discretion**: If an agent cannot support custom endpoints (e.g., uses a proprietary API), it should not advertise the `llmEndpoints` capability. | ||
|
|
||
| ## Open questions | ||
|
|
||
| ### How should provider identifiers be standardized? | ||
|
|
||
| We need to define a standard set of provider identifiers (e.g., `"anthropic"`, `"openai"`, `"google"`, `"amazon"`). Should this be: | ||
xtmq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - A fixed enum in the protocol specification? | ||
| - An extensible set with well-known values and support for custom strings? | ||
| - Defined in a separate registry/document that can be updated independently? | ||
|
|
||
| ### How should model availability be handled? | ||
|
|
||
| When a custom endpoint is provided, it may only support a subset of models. For example, a self-hosted vLLM server might only have `llama-3-70b` available, while the agent normally advertises `claude-3-opus`, `gpt-4`, etc. | ||
xtmq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## Frequently asked questions | ||
|
|
||
| > What questions have arisen over the course of authoring this document? | ||
|
|
||
| ### Why not pass endpoints in the `initialize` request? | ||
|
|
||
| Passing endpoints directly in `initialize` would require the client to have already resolved credentials and configured endpoints before knowing whether the agent supports this feature. In practice, the client needs to inspect the agent's capabilities first to decide its authorization strategy — for example, whether to route through a corporate proxy or use direct credentials. A dedicated method after initialization solves this chicken-and-egg problem and keeps capability negotiation separate from endpoint configuration. | ||
xtmq marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Why not pass endpoint when selecting a model? | ||
|
|
||
| One option would be to pass the endpoint URL and credentials when the user selects a model (e.g., in `session/new` or a model selection method). | ||
|
|
||
| Many agents throw authentication errors before the model selection happens. This makes the flow unreliable. | ||
|
|
||
| ### Why not use environment variables or command-line arguments? | ||
|
|
||
| One option would be to pass endpoint configuration via environment variables (like `OPENAI_API_BASE`) or command-line arguments when starting the agent process. | ||
|
|
||
| This approach has significant drawbacks: | ||
| - With multiple providers, the configuration becomes complex JSON that is awkward to pass via command-line arguments | ||
| - Environment variables may be logged or visible to other processes, creating security concerns | ||
| - Requires knowledge of agent-specific variable names or argument formats | ||
| - No standardized way to confirm the agent accepted the configuration | ||
|
|
||
| ### What if the agent doesn't support custom endpoints? | ||
|
|
||
| If the agent doesn't support custom endpoints, it will not advertise `llmEndpoints: true` in `agentCapabilities` during initialization. The client can detect this and choose an alternative authorization and configuration strategy, or proceed using the agent's default endpoints. | ||
|
|
||
| ## Revision history | ||
|
|
||
| - 2026-03-04: Revised to use dedicated `setLlmEndpoints` method with capability advertisement | ||
| - 2026-02-02: Initial draft - preliminary proposal to start discussion | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.