Connecting to other LLMs
An adapter is what connects Search2o to an LLM. Three adapters are bundled, and they already cover every endpoint that speaks the OpenAI, Anthropic or Gemini protocol. An LLM with an interface of its own needs an adapter class, written in Python and registered through the allowlist.
First, try a bundled adapter
Many LLMs are reachable with the adapters that are already there. A private deployment, a gateway, or a vendor that offers an OpenAI-compatible API needs no code at all: create an LLM profile under Profiles › LLM, pick the adapter that matches the protocol (openai, anthropic or gemini), and set the URL, the headers and the model. See LLM vendors.
Each bundled adapter says so itself. The GUI shows the adapter's description when a profile is created — the OpenAI one reads “Adapter for OpenAI ChatGPT responses API or any vendor that is compatible with it”.
When you need an adapter of your own
An adapter turns the request that Search2o builds — prompt, tools, model and limits — into the vendor's request body, and turns the vendor's response back into Search2o's form. Write one only when the vendor's protocol matches none of the three.
BaseLlmAdapter, for most APIs
search2o.llm.basellmadapter.BaseLlmAdapter does the assembly and the control flow. It builds the request in a fixed order, merges the profile's additionalParams over the result, and reads the response in a fixed order. You supply only the vendor-specific pieces, as these methods:
| Method | What it does |
|---|---|
namefrom LlmAdapter | The adapter's name, as it appears in a profile's adapter field. |
descriptionfrom LlmAdapter | One line, shown in the GUI when a profile is created. |
set_model | Put the profile's model into the request parameters. |
set_max_tokens | Put the token ceiling into the request parameters. |
set_tools | Express the agent's tools in the vendor's schema. |
set_system_prompt | Place the system prompt where the vendor expects it, in the parameters or as a message. |
set_messages_user_entry | Append one user message. |
set_messages_assistant_response_content_output | Append an earlier assistant answer. |
set_messages_assistant_response_tool_calls | Append the assistant's earlier tool calls. |
set_messages_tool_results | Append the results of those tool calls. |
set_response_flags | Read success or failure from the response. |
set_token_counts | Read the token counts, which the cost report is computed from. |
set_assistant_vendor | Read the answer: either tool calls or content. A response with neither is an error. |
BaseLlmAdapter walks the prompt for you and calls the four message methods in the order the conversation happened, so an adapter never has to sort the history itself. get_error has a working implementation that reads the response's error field; override it when the vendor reports errors differently.
LlmAdapter, for anything else
search2o.llm.llmadapter.LlmAdapter is the bare interface, for a protocol so different that the assembly above does not help. Five methods, and nothing is done for you: name, description, process_request (an LlmRequestModel in, the request body out), process_response (the response in, an LlmResponseModel out), and get_error.
The bundled adapters in search2o.llm — openaiadapter.py, anthropicadapter.py and geminiadapter.py — are the reference implementations, and each is a short file.
Registering it
- The class belongs in the Python environment that the agent server runs in.
- Add the class to the allowlist as
mypackage.myadapter.MyAdapterand save. - The agent server instantiates every allowlisted subclass of
LlmAdapterwhen the server loads the allowlist, and lists those adapters under Adapters when a new LLM profile is created. An adapter whose constructor fails is written to the server's log.
The class needs a constructor that takes no arguments. Reports group spend under the profile's vendor field, so set that field to the vendor's name, whatever the adapter is called.

