openclaw - ✅(Solved) Fix [Feature]: Support client-provided tools on /v1/chat/completions endpoint (tool passthrough) [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#54405Fetched 2026-04-08 01:28:02
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Participants
  • The /v1/responses endpoint already documents client tool support (tools, tool_choice, function_call_output loop).
  • /v1/chat/completions does not mention client tools at all.
  • Home Assistant's Extended OpenAI Conversation integration uses Chat Completions (not Responses), so it cannot benefit from the Responses endpoint's tool support.
  • This is likely the most common integration pattern for HA + OpenClaw voice control.

Root Cause

  • The /v1/responses endpoint already documents client tool support (tools, tool_choice, function_call_output loop).
  • /v1/chat/completions does not mention client tools at all.
  • Home Assistant's Extended OpenAI Conversation integration uses Chat Completions (not Responses), so it cannot benefit from the Responses endpoint's tool support.
  • This is likely the most common integration pattern for HA + OpenClaw voice control.

Fix Action

Workaround

Currently the only workaround is to give the agent direct HA REST API access (URL + long-lived token) and have it call POST /api/services/... via exec/web_fetch, bypassing HA's native tool mechanism entirely.

PR fix notes

PR #66278: fix(gateway): align OpenAI chat completions tool protocol

Description (problem / solution / changelog)

Summary

  • Problem: /v1/chat/completions did not align with OpenResponses tool-calling behavior. It ignored client-provided tools / tool_choice, did not return OpenAI-compatible tool_calls, and did not support the chat-completions tool-result follow-up loop.
  • Why it matters: OpenAI-compatible clients (including HA-style integrations) could not complete the normal request -> tool call -> client executes tool -> tool result -> follow-up turn flow.
  • What changed: the gateway now supports Chat Completions function tools and tool-choice parsing, emits tool_calls in non-stream responses (finish_reason: "tool_calls"), emits delta.tool_calls in stream chunks with index, and accepts role: "tool" + tool_call_id follow-up messages.
  • What changed (stream finalize safety): stream finalization now keeps a short result-aware window so early lifecycle-end events do not drop pending tool-call metadata, while non-usage streams still close promptly.
  • Scope boundary: no auth/model-routing changes; unsupported tool_choice variants like allowed_tools / custom still fail fast with invalid_request_error.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #54405
  • Closes #54174
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: the OpenAI-compatible /v1/chat/completions adapter lacked client-tool request parsing, tool-call response mapping, and tool-result follow-up handling, even though adjacent paths already had tool-loop concepts.
  • Missing detection / guardrail: no dedicated contract tests were asserting Chat Completions tool-protocol behavior on this adapter.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test file: src/gateway/openai-http.test.ts
  • Locked scenarios:
    • tools/tool_choice parsing (none / auto / required / named function)
    • non-stream message.tool_calls + finish_reason: "tool_calls"
    • stream delta.tool_calls[index] + terminal finish_reason: "tool_calls"
    • role: "tool" + tool_call_id follow-up handling
    • disconnect/finalize race behavior for stream paths

User-visible / Behavior Changes

  • /v1/chat/completions now accepts OpenAI Chat function tools (tools) and tool_choice.
  • Non-stream tool-use responses now return message.tool_calls and finish_reason: "tool_calls".
  • Stream tool-use responses now emit delta.tool_calls chunks and terminate with finish_reason: "tool_calls".
  • Follow-up requests can return tool results via role: "tool" + tool_call_id.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)

Repro + Verification

Environment

  • OS: macOS
  • Runtime: local gateway
  • Endpoint: /v1/chat/completions

Verification run

  • pnpm test src/gateway/openai-http.test.ts
  • pnpm test src/gateway/openresponses-http.test.ts
  • pnpm test src/gateway/openai-http.test.ts -t "disconnect"
  • pnpm check

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: tool parsing, tool-choice behavior, non-stream and stream tool-call output, tool-result follow-up, stream finalize/disconnect behavior.
  • Not fully verified: full third-party OpenAI-compatible client matrix.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)

Risks and Mitigations

  • Risk: clients using broader tool_choice variants outside function-tool subset.
    • Mitigation: explicit fast-fail invalid_request_error instead of silent mismatch.
  • Risk: stream finalization race can drop late tool metadata.
    • Mitigation: result-aware finalize handling + targeted stream tests.

Trade-offs / Deferred follow-up

  • Current scope focuses on the concrete Chat Completions function-tool protocol gap.
  • Deferred: broader Chat tool_choice variants (allowed_tools / custom) can be added later via the same shared mapping seam.

Evidence links

  • src/gateway/openai-http.ts
  • src/gateway/openai-http.test.ts

Changed files

  • src/gateway/openai-http.test.ts (modified, +499/-0)
  • src/gateway/openai-http.ts (modified, +349/-9)
RAW_BUFFERClick to expand / collapse

Problem

When using OpenClaw's /v1/chat/completions endpoint as a backend for Home Assistant Extended OpenAI Conversation, HA passes service-control tools (e.g. execute_services) in the request body. However, OpenClaw replaces client-provided tools with the agent's own toolset (read, write, exec, etc.), so the HA tools never reach the model.

This means the agent can see HA entity states (passed in the system prompt) but cannot call HA services to actually control devices.

Expected behavior

Client-provided tools in the /v1/chat/completions request body should be forwarded to the model alongside (or instead of) the agent's built-in tools — similar to how /v1/responses already supports client tool definitions.

When the model invokes a client-provided tool, the response should return a tool_calls entry so the client (HA) can execute it and send back the result.

Context

  • The /v1/responses endpoint already documents client tool support (tools, tool_choice, function_call_output loop).
  • /v1/chat/completions does not mention client tools at all.
  • Home Assistant's Extended OpenAI Conversation integration uses Chat Completions (not Responses), so it cannot benefit from the Responses endpoint's tool support.
  • This is likely the most common integration pattern for HA + OpenClaw voice control.

Use case

  1. User says "turn off the living room lights" via HA voice pipeline
  2. HA sends a /v1/chat/completions request with execute_services as a tool
  3. OpenClaw agent calls execute_services with the appropriate entity/service
  4. HA executes the service call and returns the result
  5. Agent responds: "Done — living room lights off."

Workaround

Currently the only workaround is to give the agent direct HA REST API access (URL + long-lived token) and have it call POST /api/services/... via exec/web_fetch, bypassing HA's native tool mechanism entirely.

Environment

  • OpenClaw 2026.3.8
  • Home Assistant with Extended OpenAI Conversation (HACS)
  • Agent model: Claude Sonnet 4.6

extent analysis

Fix Plan

To fix this issue, we need to modify the OpenClaw /v1/chat/completions endpoint to support client-provided tools. Here are the steps:

  • Update the endpoint to accept a tools parameter in the request body.
  • Modify the agent's toolset to include the client-provided tools.
  • When the model invokes a client-provided tool, return a tool_calls entry in the response.

Example Code

# Update the /v1/chat/completions endpoint to accept client-provided tools
from fastapi import FastAPI, Request
from pydantic import BaseModel

app = FastAPI()

class ChatCompletionRequest(BaseModel):
    model: str
    prompt: str
    tools: dict = {}  # Add support for client-provided tools

@app.post("/v1/chat/completions")
async def chat_completions(request: ChatCompletionRequest):
    # Modify the agent's toolset to include client-provided tools
    agent_tools = {"read", "write", "exec"}
    agent_tools.update(request.tools)

    # Call the model with the updated toolset
    model_response = call_model(request.model, request.prompt, agent_tools)

    # Return a tool_calls entry in the response if a client-provided tool is invoked
    if "tool_calls" in model_response:
        return {"tool_calls": model_response["tool_calls"]}

    return {"response": model_response}

Verification

To verify that the fix worked, you can test the /v1/chat/completions endpoint with a client-provided tool. For example, you can send a request with the execute_services tool and verify that the agent calls the tool and returns a tool_calls entry in the response.

Extra Tips

  • Make sure to update the OpenClaw documentation to reflect the new support for client-provided tools in the /v1/chat/completions endpoint.
  • Consider adding validation for client-provided tools to ensure they are valid and secure.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Client-provided tools in the /v1/chat/completions request body should be forwarded to the model alongside (or instead of) the agent's built-in tools — similar to how /v1/responses already supports client tool definitions.

When the model invokes a client-provided tool, the response should return a tool_calls entry so the client (HA) can execute it and send back the result.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Feature]: Support client-provided tools on /v1/chat/completions endpoint (tool passthrough) [1 pull requests, 1 participants]