Introduction

DSH’s plugin ecosystem breaks down different capabilities into installable components. dsh-openai-gateway solves a specific problem: OpenAI clients typically only call standard endpoints like /v1/chat/completions and /v1/models, whereas DSH Agent sessions are also backed by tools and workspaces.

This plugin exposes DeepSeek Harness (DSH) as an OpenAI-compatible API server: after configuring base_url and the API key, clients can invoke DSH’s real Agent sessions. Below is an introduction to its features, installation methods, typical usage, and precautions.

What is this

dsh-openai-gateway is a DSH plugin maintained by backrooms-yrc. The version introduced here is v0.1.1 with an MIT license.

It provides the following core endpoints:

  • POST /v1/chat/completions, supporting streaming and non-streaming
  • GET /v1/models
  • GET /v1/models/:id
  • GET /healthz, an unauthenticated health check

Every API call is backed by a real DSH Agent session equipped with tools and a workspace. The plugin includes an independent HTTP listener and Bearer authentication. If the API key is not configured, a key is generated upon the first start and written to disk with 0600 permissions.

Installation and Enabling

First, install the plugin:

dsh plugin --profile web add github:backrooms-yrc/dsh-openai-gateway#v0.1.1

Restarting dsh web is required for a new package. After restarting, check the actual listening status:

cat $DSH_HOME/openai-gateway/state.json

Then check the API key:

cat $DSH_HOME/openai-gateway/api-keys.json

DSH_HOME defaults to ~/.dsh; if DSH_HOME is customized via an environment variable, the actual directory takes precedence.

If the API key is not configured, the plugin will automatically generate one on first start and write it to:

$DSH_HOME/openai-gateway/api-keys.json

The file permissions are 0600.

The health check endpoint does not require authentication:

curl http://127.0.0.1:41540/healthz

Ports and Listening

The default listening address is:

127.0.0.1:41540

The 41540 here is the default port of dsh-openai-gateway, not an official DSH convention.

If the port is occupied, the plugin logs FATAL, state.json does not update, and /healthz becomes unavailable. Simply change the port in this case.

You can also set port to 0 to let the operating system allocate a random port. After random allocation, the actual port is written to:

$DSH_HOME/openai-gateway/state.json

Configuration Reference

The configuration items listed below use the plugin’s default values as a reference:

Key Default Value Description
host 127.0.0.1 Binds only to the loopback address by default
port 41540 Listening port; set to 0 for random allocation, actual value in state.json
sessionMode both Supports both stateless and sticky sessions; when set to stateless, sticky session requests are rejected
maxSessions 16 Limit for sticky session bookkeeping, using the LRU strategy
timeoutSeconds 300 Timeout per round; after timeout, the Agent is cancelled and 504 is returned
workspace.cwd Empty string Agent working directory; if empty, $DSH_HOME/openai-gateway/workspace is used

Making the First Call

Replace $KEY with the key from api-keys.json, and replace $PORT with the port from state.json:

curl http://127.0.0.1:$PORT/v1/chat/completions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"model":"default","messages":[{"role":"user","content":"你好"}]}'

The model parameter supports three formats:

  • default: Follows DSH’s current default model
  • provider/model: Precisely routes to a specific provider and model
  • Bare model name: Automatically matches the provider via the DSH directory

The complete list of models can be queried via GET /v1/models.

Session Modes

By default, the plugin supports stateless sessions as well as sticky sessions.

The characteristic of stateless sessions is that the messages in the request are concatenated into a single prompt, and the session is destroyed after the round ends. It is suitable for direct integration of standard OpenAI clients.

Sticky sessions are suitable for continuous multi-round tasks. The first request should carry:

X-DSH-Session: new

Or in the extension field of the request body:

"dsh_session": "new"

The response will return a dsh_session_id. Subsequent requests carry this ID to reuse the same Agent session.

Example:

curl -X POST http://127.0.0.1:$PORT/v1/chat/completions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "X-DSH-Session: new" \
  -d '{"model":"default","messages":[{"role":"user","content":"记住一个词:蓝鲸"}]}'

Record the dsh_session_id in the response. In the second round, only send the new user message:

curl -X POST http://127.0.0.1:$PORT/v1/chat/completions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "X-DSH-Session: openai-..." \
  -d '{"model":"default","messages":[{"role":"user","content":"刚才让你记住的词是什么?"}]}'

If sessionMode is set to stateless, sticky session requests will be rejected.

Integration with OpenAI Clients

Any OpenAI client only needs to configure base_url and the API key.

Python example:

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:41540/v1",
    api_key="sk-dsh-...",
)

resp = client.chat.completions.create(
    model="default",
    messages=[{"role": "user", "content": "你好"}],
)

print(resp.choices[0].message.content)

Streaming responses also support the reasoning increment for reasoning models, with the field being delta.reasoning_content, in a style similar to DeepSeek.

stream = client.chat.completions.create(
    model="default",
    stream=True,
    messages=[{"role": "user", "content": "解释一下 SSE"}],
)

for chunk in stream:
    delta = chunk.choices[0].delta

    reasoning = getattr(delta, "reasoning_content", None)
    if reasoning:
        print("[思考]", reasoning, end="", flush=True)

    if delta.content:
        print(delta.content, end="", flush=True)

Extension Fields and Tool Calls

The plugin provides extension fields in the response:

  • dsh_session_id
  • dsh_tool_calls

Tool calls are presented as comment frames in the SSE stream:

: dsh tool-call <name>

These extension fields do not break the parsing of standard OpenAI clients.

Reverse Proxy

The default host is 127.0.0.1, binding only to the loopback address. If you need to provide services externally, it is recommended to expose them through a reverse proxy, with the reverse proxy handling TLS.

Using nginx as an example, at least /v1/ needs to be proxied, and SSE buffering needs to be disabled:

location ^~ /v1/ {
    proxy_pass http://127.0.0.1:41540;
    proxy_buffering off;
}

The 41540 should be replaced with the actual port from state.json.

Afterward, clients can configure the base URL as:

https://your-domain/v1

Applicable Scenarios and Notes

This plugin is suitable for scenarios where users are already using DSH and want to integrate DSH Agent with OpenAI SDK, scripts, or other OpenAI-compatible clients.

Pre-use precautions:

  • The plugin joins the runtime environment of dsh web and runs with the permissions of the current DSH process; it is recommended to check the source code and MIT license before installing.
  • By default, it only listens on the loopback address; external deployment is suggested via a reverse proxy.
  • The default port 41540 is the default for this plugin, not an official DSH convention.
  • When port is 0, a random port is allocated; the actual value is determined by state.json.
  • Sticky sessions have a limit on bookkeeping, with the default maxSessions being 16.
  • The single-round timeout defaults to 300 seconds; after timeout, the Agent is cancelled and 504 is returned.
  • workspace.cwd defaults to empty; in this case, $DSH_HOME/openai-gateway/workspace is used.

The current version is v0.1.1, implemented and tested for DSH 0.1.1-rc.2. It is a developer preview with no compatibility guarantees at this time.

Known limitations include:

  • tool_calls are not projected into OpenAI tool call frames
  • tools and tool_choice in the request body are ignored
  • No quota or rate limiting per key
  • maxSessions is the limit for sticky session bookkeeping; old Agents evicted by the DSH registry are reclaimed based on its own strategy

If installed via a local path or link, the plugin does not automatically install peer dependencies. You need to ensure the following packages are resolvable:

@deepseek-ai/dsh-agent
@deepseek-ai/dsh-llm
@deepseek-ai/dsh-session
@deepseek-ai/dsh-home-paths
@deepseek-ai/schemastery

Conclusion

The value of dsh-openai-gateway lies in its ability to wrap the session, tool, and workspace capabilities of DSH Agent into standard OpenAI endpoints. As long as you configure base_url and the API key, OpenAI clients can initiate calls, and behind every call is a real DSH Agent session.

Code repository:

https://github.com/backrooms-yrc/dsh-openai-gateway

Plugin entry page provided by the plugin clue:

https://www.skillhub.cn/plugins/backrooms-yrc/dsh-openai-gateway

The entry page is subject to the actual accessible address.