# DeepSeek Harness

DeepSeek Harness (`dsh`) is DeepSeek's open-source agent harness. It runs as a web interface or a desktop app. These steps add the exchange to it as a custom provider with an OpenAI-compatible endpoint.

A patch file holds the settings, and one environment variable holds the key. They apply only to the shell that you start it from.

## Start with the Liquid CLI

The [Liquid CLI](https://inference.ai.exchange/docs/cli.md) writes the patch and starts `dsh web` with the exchange as its provider. It sets the key for that process only.

```bash
curl -fsSL https://inference.ai.exchange/cli/install.sh | bash
liquid login --browser --keys
liquid keys create laptop --save
liquid dsh
```

`liquid dsh` reads the model list of the exchange when it starts. It writes each router model, preset and model that accepts tool calls into the patch, so the model list of DeepSeek Harness shows them.

- Each entry has the input window of its model and states whether the model reads images.
- `--filter` narrows the list.
- If the exchange cannot be reached, the patch holds the default model only.

## Before you start

- A workspace with a balance and a `spend` key. See [API keys](https://inference.ai.exchange/docs/keys.md).
- A model that supports tool calls and streaming.

## 1. Install DeepSeek Harness

```bash
npm install -g @deepseek-ai/dsh
```

## 2. Export the buyer key

Replace the placeholder with your buyer key. Use the same shell for each command below.

```bash
export LIQUID_API_KEY=sk-liquid-...
```

| Setting          | Purpose                                                              |
| ---------------- | -------------------------------------------------------------------- |
| `LIQUID_API_KEY` | Your buyer key. The patch names this variable and never holds a key. |

## 3. Write the patch

DeepSeek Harness reads extra settings from a patch file. Create the folder, then write the file:

```bash
mkdir -p ~/.liquid
```

```bash
cat > ~/.liquid/dsh.patch.yml <<'EOF'
- id: llm-pi-ai
  config:
    providers:
      liquid:
        displayName: Liquid Inference
        apiKeyEnv: LIQUID_API_KEY
        api: openai-completions
        baseURL: "https://router.inference.ai.exchange/v1"
        headers:
          X-Title: DeepSeek Harness
          x-liquid-cap-usd: "1.00"
        defaultContextWindow: 128000
        defaultMaxTokens: 16384
        cacheRetention: long
        compat:
          supportsLongCacheRetention: true
        models:
          - id: "liquid.auto"
            input: [text, image]
- id: agent-default-model
  config:
    provider: liquid
    model: "liquid.auto"
- {id: web-search-deepseek, disabled: true}
- id: tool-web
  config:
    search: false

EOF
```

| Setting                      | Why it is set                                                                                     |
| ---------------------------- | ------------------------------------------------------------------------------------------------- |
| `displayName`                | Shows the provider in the model list.                                                             |
| `apiKeyEnv`                  | Names the variable that holds the key.                                                            |
| `api`                        | Selects OpenAI Chat Completions.                                                                  |
| `baseURL`                    | The exchange URL, with `/v1`.                                                                     |
| `X-Title`                    | Gives each request the DeepSeek Harness client label.                                             |
| `x-liquid-cap-usd`           | Limits the charge for each request.                                                               |
| `defaultContextWindow`       | The input window of the model. DeepSeek Harness compacts a session by it.                         |
| `defaultMaxTokens`           | Limits the output of each request, and so the cap of each request.                                |
| `cacheRetention`             | Sends the session as `prompt_cache_key`, so the exchange keeps the turns of one session together. |
| `supportsLongCacheRetention` | Allows `cacheRetention: long` for this provider.                                                  |
| `input`                      | Lets the model receive images.                                                                    |
| `provider`                   | Makes the exchange the provider of the default model.                                             |
| `model`                      | Makes the model the default.                                                                      |
| `search`                     | Turns off the `web_search` tool and keeps `web_fetch`.                                            |

The last lines turn off web search. The search backend `web-search-deepseek` calls DeepSeek's own API with `DEEPSEEK_API_KEY`, which the exchange does not accept. The `web_fetch` tool reads a page over plain HTTP and stays on.

## 4. Start the web interface

```bash
dsh web --patch ~/.liquid/dsh.patch.yml
```

Open the address that `dsh` prints. Choose a workspace. Send a short request, then open **Credits → Receipts** to check the charge.

## Notes

- To use another model, add an entry under `models` and change `model`. Use an exact model, a router model or a preset. To get the current names, see the **Market** page. See [Market data](https://inference.ai.exchange/docs/market.md).
- The cap limits each request. It does not limit the total charge of a task. To limit total spend, set a spending limit on the key. See [API keys](https://inference.ai.exchange/docs/keys.md).
- The model sends no reasoning effort. For a reasoning model, declare `reasoningEfforts` on its entry, for example `{low: low, high: high}`. Each key is a level of DeepSeek Harness and each value is the effort that the exchange receives. The exchange sends a request with a reasoning effort only to an offer that accepts one.
- The patch uses the route of DeepSeek Harness for other endpoints. DeepSeek's own route also sends the session record and the plugin list in each request. This route sends neither.

## Troubleshooting

| Symptom                                          | Cause and fix                                                                |
| ------------------------------------------------ | ---------------------------------------------------------------------------- |
| `MISSING_CREDENTIAL`                             | Export `LIQUID_API_KEY` in the shell that starts `dsh`.                      |
| `401`                                            | The key is empty, wrong or expired. Check `LIQUID_API_KEY`.                  |
| `403`                                            | Check the key's `spend` scope, address restriction and preset rules.         |
| `402`                                            | Add credit to the workspace or check the key's spend limit.                  |
| `404`                                            | Keep `/v1` at the end of `baseURL`.                                          |
| `model_not_found`                                | The model ID is not on the book. Use an exact name from the **Market** page. |
| `reasoning.effort` is not supported by any offer | Remove `reasoningEfforts` from the model entry.                              |
| A refusal that names the output limit            | Set `defaultMaxTokens` to 16384 or less.                                     |

See [Errors](https://inference.ai.exchange/docs/errors.md) for the exchange's error codes and causes.

## Next steps

- [Pi](https://inference.ai.exchange/docs/connect-pi.md): another terminal agent with a provider file.
- [Market data](https://inference.ai.exchange/docs/market.md): models and live offers.
- [API keys](https://inference.ai.exchange/docs/keys.md): scopes and spending limits.
