> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oumi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# RUN YOUR AGENT AS THE MAIN MODEL IN HERMES

> Serve your fine-tuned tool-calling model from Oumi and use it as the model of a Hermes Agent profile

An agent that you train on Oumi can run outside Oumi. [Hermes Agent](https://hermes-agent.nousresearch.com/docs/) is an open-source [agent harness](https://docs.oumi.ai/reference/agent-harnesses.md) from Nous Research that runs in your terminal and in messaging apps. You deploy your fine-tuned model on Oumi, implement its tools as a Hermes plugin, and add your deployment to a Hermes profile as a custom provider.

You do not write or maintain an agent loop of your own. Hermes supplies the loop, the terminal interface, and the session history, and your small fine-tuned model supplies the tool-calling behavior at a fraction of the cost and latency of a frontier model.

In this guide, your model is the main model of a Hermes profile that you use only for your agent. To keep your usual model in Hermes and call your agent only when you need it, [run it as a subagent](https://docs.oumi.ai/guides/agents/run-your-agent/hermes/subagent.md) instead.

This guide uses a stock lookup agent as its example. The agent has two tools: `search_company` finds the ticker symbol for a company name, and `get_stock_price` returns the latest price for a ticker.

> [!WARNING]
>
> Hermes always builds its own system prompt around your instructions. Even in a profile with only your tools, the system prompt also contains Hermes guidance about tool calls, the current date and time, and details about your machine, such as the working directory. If your model did not see this text during training, its results in Hermes can differ from your evaluations. In that case, you may want to consider [running it as a subagent](https://docs.oumi.ai/guides/agents/run-your-agent/hermes/subagent.md), where your model receives only the system prompt from your training data.

***

## HOW THE PIECES CONNECT

![The Hermes agent loop on your machine sends messages and tools to your Oumi deployment, runs each tool call in your Hermes plugin, and returns the final reply to you](https://mintcdn.com/oumi/utu7_qxGqvVUwYVB/images/hermes-connection-light.svg?fit=max\&auto=format\&n=utu7_qxGqvVUwYVB\&q=85\&s=cfd82189184810f995b07c31ee7d83bb)

Oumi serves the model. Hermes runs everything else on your machine, including your tool code, so your tools can reach real data that Oumi cannot.

***

## BEFORE YOU START

You will need:

* An Oumi project.
* Hermes, installed on your machine by following the [Hermes installation](https://hermes-agent.nousresearch.com/docs/getting-started/installation) instructions.
* A personal Oumi API key from **User Settings > API Keys**.

***

**1. Train a tool-calling model**

Ask FAiE to help you build the agent, or follow the [agents workflow](https://docs.oumi.ai/guides/agents.md#a-typical-workflow) yourself:

1. [Create a tool](https://docs.oumi.ai/guides/agents/tools.md) for each function that your agent calls. For the example, create `search_company` and `get_stock_price`.
2. Give each tool a [tool implementation](https://docs.oumi.ai/guides/agents/tool-implementations.md). A simulated implementation is enough to generate training data. Hermes calls your real code later.
3. Collect the prompts that your agent must handle, and [generate training conversations](https://docs.oumi.ai/guides/synthesis/how-it-works.md#add-tools-and-a-simulated-user) with a strong teacher model.
4. [Train](https://docs.oumi.ai/guides/training.md) a base model that [supports tool calling](https://docs.oumi.ai/guides/training/model-selection.md#tool-use) on the best conversations.
5. [Evaluate](https://docs.oumi.ai/guides/evaluations/running.md#add-tools-and-a-simulated-user) the trained model against the teacher with your tools attached.

Keep a copy of the system prompt from your training data. You use it again in Hermes.

**2. Deploy the model**

[Deploy your trained model](https://docs.oumi.ai/guides/deployment/deploy-a-model.md) and wait until the deployment is `Active`. Copy its model path from the deployment page. The model path has the form `projects/{project_id}/deployments/{deployment_id}`.

**3. Create a Hermes profile for your agent**

A [Hermes profile](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) is a separate Hermes home directory with its own configuration, plugins, and identity. A profile for your agent keeps its model, tools, and system prompt apart from your usual Hermes setup.

```bash theme={null}
hermes profile create stock-agent
```

Hermes creates `~/.hermes/profiles/stock-agent/` and a `stock-agent` command that runs Hermes with that profile.

Save the system prompt from your training data as the profile's `SOUL.md`. Hermes uses `SOUL.md` as the agent's identity, in place of its default identity:

```bash theme={null}
cp ./stock-agent-system-prompt.md ~/.hermes/profiles/stock-agent/SOUL.md
```

Add your Oumi API key to the profile's `.env` file, and make the file readable only by you:

```bash ~/.hermes/profiles/stock-agent/.env theme={null}
OUMI_API_KEY=your-oumi-api-key
```

```bash theme={null}
chmod 600 ~/.hermes/profiles/stock-agent/.env
```

**4. Implement the tools in Hermes**

During training or evaluation on the Oumi platform, a [tool implementation](https://docs.oumi.ai/guides/agents/tool-implementations.md) answered each tool call. In Hermes, a [plugin](https://hermes-agent.nousresearch.com/docs/user-guide/features/plugins) answers it. A plugin is a directory with a `plugin.yaml` manifest and an `__init__.py` file whose `register` function registers the tools that your model knows how to call.

The model learned your tools from their Oumi definitions. Make each Hermes tool match its Oumi tool:

* **Name:** The same `toolName`, for example `search_company`. If the names differ, the model calls a tool that Hermes does not have.
* **Parameters:** The same parameter names, types, and required fields.
* **Description:** The same text, or text that is very close to it.

Create `~/.hermes/profiles/stock-agent/plugins/stock-tools/plugin.yaml`:

```yaml plugin.yaml theme={null}
name: stock-tools
version: "1.0"
description: The tools of the stock lookup agent
```

Create `~/.hermes/profiles/stock-agent/plugins/stock-tools/__init__.py`:

```python __init__.py theme={null}
import json
import urllib.error
import urllib.parse
import urllib.request

API = "https://api.example-stocks.com"

SEARCH_COMPANY = {
    "name": "search_company",
    "description": "Find a company's stock ticker symbol by company name. Call this before get_stock_price.",
    "parameters": {
        "type": "object",
        "properties": {"name": {"type": "string", "description": "Company name, e.g. 'Apple'."}},
        "required": ["name"],
    },
}

GET_STOCK_PRICE = {
    "name": "get_stock_price",
    "description": "Get the latest stock price for a ticker symbol returned by search_company.",
    "parameters": {
        "type": "object",
        "properties": {"ticker": {"type": "string", "description": "Stock ticker symbol, e.g. 'AAPL'."}},
        "required": ["ticker"],
    },
}


def search_company(args: dict, **kwargs) -> str:
    found = get_json(f"{API}/search?q={urllib.parse.quote(args['name'])}")
    if found is None:
        return json.dumps({"found": False, "message": f"No company found matching \"{args['name']}\"."})
    return json.dumps({"found": True, "ticker": found["ticker"], "name": found["name"]})


def get_stock_price(args: dict, **kwargs) -> str:
    quote = get_json(f"{API}/quote/{urllib.parse.quote(args['ticker'])}")
    if quote is None:
        return json.dumps({"found": False, "message": f"No price found for \"{args['ticker']}\"."})
    return json.dumps({"found": True, "price": quote["price"], "currency": quote["currency"]})


# A 404 means "no match" and returns None. Any other failure raises, and
# Hermes sends the error to the model as the tool result.
def get_json(url: str) -> dict | None:
    try:
        with urllib.request.urlopen(url, timeout=30) as res:
            return json.load(res)
    except urllib.error.HTTPError as error:
        if error.code == 404:
            return None
        raise


def register(ctx):
    ctx.register_tool(name="search_company", toolset="stock", schema=SEARCH_COMPANY, handler=search_company)
    ctx.register_tool(name="get_stock_price", toolset="stock", schema=GET_STOCK_PRICE, handler=get_stock_price)
```

Each handler returns a JSON string, which is what the model reads. A tool that finds no match returns a result that says so. A tool whose data source fails raises an error, and Hermes sends that error to the model as the tool result. Neither path invents a value.

> [!TIP]
>
> You can have Hermes write the plugin for you. Start Hermes with a frontier model, paste the JSON of each Oumi tool from its detail page, and ask: "Write a Hermes plugin in `~/.hermes/profiles/stock-agent/plugins/stock-tools/` that registers these tools with the same names and parameters in a toolset named `stock`. Use `<your data source>` to answer them." Review the code before you enable it, because a plugin runs with your user's permissions.

Plugins are off until you enable them. Enable the plugin in the profile:

```bash theme={null}
stock-agent plugins enable stock-tools
```

**5. Add the deployment to the profile**

Add an `oumi` provider to `~/.hermes/profiles/stock-agent/config.yaml`, and make it the profile's model. Create the file if it does not exist.

```yaml ~/.hermes/profiles/stock-agent/config.yaml theme={null}
providers:
  oumi:
    api: https://inference.oumi.ai/v1
    key_env: OUMI_API_KEY
    transport: chat_completions
    discover_models: false
    models:
      projects/{project_id}/deployments/{deployment_id}:
        context_length: 32768

model:
  provider: custom:oumi
  default: projects/{project_id}/deployments/{deployment_id}
```

| Field | Value |
| - | - |
| `providers.oumi.api` | `https://inference.oumi.ai/v1`. Your deployment's endpoint is [OpenAI-compatible](https://docs.oumi.ai/guides/deployment/calling-your-endpoint.md). |
| `providers.oumi.key_env` | The variable in the profile's `.env` file that holds your Oumi API key. |
| `providers.oumi.transport` | `chat_completions`, so that Hermes sends requests in the OpenAI chat completions format. |
| `providers.oumi.discover_models` | `false`, so that Hermes uses only the models in this entry instead of listing the models of the endpoint. |
| `providers.oumi.models` | The model path of your deployment, exactly as the deployment page shows it. Set `context_length` to a value within the limit of your trained model. Hermes uses it to decide when to compress the conversation. |
| `model.provider` | `custom:oumi`, the `oumi` entry under `providers`. |
| `model.default` | The model path of your deployment again. |

See [Named custom providers](https://hermes-agent.nousresearch.com/docs/integrations/providers#named-custom-providers) in the Hermes documentation for the other fields of a provider entry.

**6. Run the agent**

Start Hermes with the profile and only the toolset from your plugin:

```bash theme={null}
stock-agent chat --toolsets stock
```

> [!WARNING]
>
> By default, Hermes also gives the model its own toolsets, such as terminal, file, web, and memory tools, and adds guidance for them to the system prompt. If your model did not see these during training, you may want to consider starting Hermes with `--toolsets stock`, as in the command above. Otherwise, the model can call a Hermes tool instead of your tools, or answer without calling a tool.

Then ask a question such as "How is Nucor doing today?". The model calls `search_company` to find the ticker `NUE`, calls `get_stock_price` with that ticker, and answers with the price that the tool returned. Hermes shows each tool call in the transcript.

***

## TROUBLESHOOTING

* **`429` with "Deployment is warming up":** Your deployment uses [scale-to-zero](https://docs.oumi.ai/guides/deployment/deploy-a-model.md#autoscaling-and-cost-custom-models) and has no warm replica. Wait a few minutes and send the prompt again. To prevent cold starts, set min replicas to 1.
* **`400` with "Invalid model format":** The model in `config.yaml` is not a model path. Set the key under `models` and `model.default` to `projects/{project_id}/deployments/{deployment_id}`.
* **`401` from the deployment:** Hermes did not send your Oumi API key. Make sure that `OUMI_API_KEY` is in `~/.hermes/profiles/stock-agent/.env`, and that `key_env` names that variable.
* **The model does not have your tools:** The plugin is not enabled, or Hermes did not load it. Run `stock-agent plugins enable stock-tools`, then start a new session. To see why Hermes skips a plugin, run `HERMES_PLUGINS_DEBUG=1 stock-agent plugins list`.
* **The model calls a tool that Hermes does not have:** A tool name in your plugin does not match the `toolName` in Oumi. Rename the Hermes tool, then start a new session.
* **The model answers without calling tools, or calls Hermes tools:** Start Hermes with `--toolsets stock` as shown in the last step, so that the model sees only your tools.

***

## WHAT'S NEXT

> **[Run your agent as a subagent](https://docs.oumi.ai/guides/agents/run-your-agent/hermes/subagent.md)**
>
> Keep your usual model in Hermes and give it your agent as a tool.

> **[Inference logs](https://docs.oumi.ai/guides/deployment/inference-logs.md)**
>
> Review the requests that Hermes sent to your deployment.

> **[Compounding intelligence](https://docs.oumi.ai/guides/deployment/compounding-intelligence.md)**
>
> Find where your deployed model struggles, and retrain it on targeted data.

> **[Tools](https://docs.oumi.ai/guides/agents/tools.md)**
>
> Write tool definitions that a model calls correctly.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.