Newer
Older
navi-1 / manuals / write_context_provider.md

Writing a Context Provider

Context providers inject dynamic runtime data as system messages into every LLM call. Use them when information is needed frequently and fetching it on-demand every time would be wasteful (current URL, hostname, server status, etc.).

When to use a context provider vs a tool

  • Context provider: data that is useful on every call without the model asking — server address, current environment, active config values.
  • Tool: data that is needed occasionally on demand — current weather, a file's contents, search results.

File format

Create a file in context_providers/ at the project root. File name must not start with _.

# context_providers/my_provider.py

name = "my_provider"
description = "One-line description of what this injects."
global_provider = False  # True = injected in ALL profiles automatically

async def get_context() -> str | None:
    """Return a string or None. None means skip silently."""
    return "[System] My info: ..."

Required fields

Field Type Description
name str Unique identifier
description str What data this provides
get_context async def Returns str to inject or None to skip

Optional fields

Field Type Default Description
global_provider bool False True = inject in every profile; False = only in profiles that list this name in context_providers

Enabling per-profile

For non-global providers, add the name to the profile's config.json:

"context_providers": ["my_provider"]

Activation

After writing, call reload_tools — it reloads both tools and context providers. The new data will appear in the next LLM call.

Example: inject current server hostname

# context_providers/hostname.py
import socket

name = "hostname"
description = "Injects the current server hostname."
global_provider = True

async def get_context() -> str | None:
    return f"[System] Server hostname: {socket.gethostname()}"

Notes

  • Return value is injected as role="system" right after the memory summary, before conversation history.
  • Exceptions in get_context() are caught and logged — they never crash the agent.
  • global_provider = True providers are loaded for every profile; no config change needed.
  • Built-in providers live in navi/context_providers/ and cannot be overwritten by user providers.