# 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 `_`.

```python
# 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`:
```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

```python
# 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.
