oterm/docs/tools/index.md
Yiorgis Gozadinos 781bc7c043
Read a local server's context window when the chat opens and after every reply
The window only reached the summarize capability after the first reply
reported usage, so a reopened long chat on a local server sent its
whole history uncompacted: Ollama silently drops the oldest context and
vLLM rejects the request. The chat now asks the server on mount, after
each reply whether or not it reported usage, and again after the chat
is edited, which previously kept the old model's window.

The system prompt check that drives the summary notification stays,
with the invariant it relies on stated: oterm sends its system prompt
as instructions and none of its capabilities add system prompts.

The turn helper in the widget tests waited for exactly two messages,
which a preloaded chat can never reach; it now waits for two more than
were there.
2026-09-27 13:56:12 +03:00

5.6 KiB

Tools

oterm supports integration with tools. Tools are special "functions" that can provide external information to the LLM model that it does not otherwise have access to.

With tools, you can provide the model with access to the web, run shell commands, perform RAG and more.

Use existing Model Context Protocol servers

or

create your own custom tools.

Custom tools with oterm

You can create your own custom tools and integrate them with oterm using Python entry points.

Create a python package

Create a python package that exports a callable function. The function's name, docstring, and type annotations are used to generate the tool definition for the model.

Here is an example{:target="_blank"} of a simple tool that implements an Oracle:

def oracle(question: str) -> str:
    """Function to return the Oracle's answer to any question.

    Args:
        question: The question to ask.
    """
    return "oterm"

Register the tool as an entry point

In your package's pyproject.toml, register the tool under the oterm.tools entry-point group:

[project.entry-points."oterm.tools"]
oracle = "oracle.tool:oracle"

Install and use

Install the package in the same environment where oterm is installed:

cd oracle
uv pip install . # or pip install .

That's it! oterm discovers all tools registered under the oterm.tools entry-point group at startup. You can now select the tool when creating or editing a chat.

Built-in tools

The following tools are built-in to oterm and available by default:

  • think - provides the model with a way to think about a question before answering it. This is useful for complex questions that require reasoning. Use it for adding a "thinking" step to the model's response.
  • date_time - provides the current date and time in ISO format.
  • shell - allows you to run shell commands and use the output as input to the model. Obviously this can be dangerous, so use with caution.
  • generate_image - generates an image from a text prompt using an Ollama image-generation model (e.g. x/z-image-turbo, x/flux2-klein). The default model is x/z-image-turbo; override it for a single call via the tool's model argument or globally via the OTERM_OLLAMA_IMAGE_MODEL environment variable. The image renders inline in the chat. Requires an Ollama server with an image-capable model installed; the host LLM (any provider) writes the prompt and calls the tool.

Capabilities

Alongside tools, oterm offers pydantic-ai capabilities in the tool selector, under the capabilities group:

  • web_search - searches the web. Uses the provider's native web search when available (e.g. Anthropic, OpenAI), and falls back to DuckDuckGo for providers without one (e.g. Ollama).
  • web_fetch - fetches the contents of a URL, using the provider's native URL fetching when available.
  • memory - gives the model a persistent memory notebook, shared across all chats and stored in memory.db in the oterm data directory. The model reads, writes and searches it with dedicated tools.
  • filesystem - lets the model read, write and search files under the directory oterm was started from. Paths outside it are rejected, and sensitive files (.git, .env, keys, secrets) are read-only.
  • summarize - keeps long conversations inside the model's context window. Once the conversation reaches 80% of the window, older messages are replaced by a summary written by the chat's own model, with the chat's parameters and thinking off, and the most recent 40% of the window is kept as it is. A notification says when this happens. The chat on screen and in the database keeps every message, so reopening a long chat summarizes it again on its next request. Ollama and OpenAI-compatible servers are asked for the window they run the model with when the chat opens and after each reply. Until the server reports one, which Ollama and LM Studio only do once the model is loaded, requests go out as they are.
  • speak - reads the response aloud as it streams, through piper. The voice is GLaDOS. There is no setting to change it. pydantic-ai-tts can synthesize 175 catalogue voices. You get the one from the enrichment center. Run uvx "oterm[speak]", which brings piper-tts (GPL-3.0) along with it. The capability appears in the selector only once it is installed, so if you cannot see it, it is not there. On the first response a voice model downloads and nothing whatsoever appears to happen. That is expected. Everything here is expected. oterm also sets ORT_DISABLE_TELEMETRY=1 before onnxruntime loads, unless you have already set it yourself. The Enrichment Center gathers quite enough data without help.

Tool calls in the chat

When the model invokes a tool during a response, oterm renders the call inline as a collapsible entry between any "thoughts" and the response itself:

▸ tool call: search_repo

Click the line (or its arrow) to expand it. The expanded body shows:

  • args: the arguments the model passed to the tool. Dictionaries and JSON-encoded strings are pretty-printed with syntax highlighting; plain strings are shown verbatim and truncated if very long.
  • result: the value the tool returned, formatted the same way. Appears once the tool has finished.

Click again to collapse. Multiple calls within the same turn each get their own entry.