Skip to content

Support connector-scoped OpenAI-compatible request behavior - #9826

Open
dfliess wants to merge 2 commits into
rilldata:mainfrom
dfliess:fix/openai-compatible-request-behavior
Open

dfliess wants to merge 2 commits into
rilldata:mainfrom
dfliess:fix/openai-compatible-request-behavior

Conversation

@dfliess

@dfliess dfliess commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add connector-scoped structured_output_mode with the existing json_schema behavior as the default and a json_object fallback that includes the schema in the prompt
  • add a validated extra_body map for provider-specific chat completion fields while rejecting overrides of core request and response-shape fields
  • canonicalize and hash connection cache configuration so nested JSON values cannot alias and credentials are not embedded in cache keys
  • document configuration for OpenAI-compatible endpoints

Motivation

OpenAI-compatible providers differ in structured-output support and provider-specific request extensions. This was motivated by an interoperability report in kairosagentica/kairos-cloud#145.

The defaults remain unchanged for existing OpenAI connectors, and all new behavior is configured per connector.

Test plan

  • go test -race ./runtime/drivers/openai -run "TestComplete(AppliesConnectorRequestBehavior|PassesNestedExtraBody|DefaultsToJSONSchema)|TestOpenValidatesProviderRequestBehavior" -count=1
  • go test ./runtime -run TestGenerateConnectionKey -count=1
  • go test ./runtime/... -run "^$"
  • go vet ./runtime/drivers/openai ./runtime
  • git diff --check upstream/main...HEAD

@nishantmonu51 nishantmonu51 added Type:Feature New feature request Area:Connectors Size:M Medium change: 100-499 lines labels Sep 1, 2026

@nishantmonu51 nishantmonu51 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two notes alongside the inline comment, plus one clause on staleness.

  • The %#v fallback in writeConfigHash (runtime/connection_cache.go:216) is effectively unreachable: instance connector config comes from structpb.Struct.AsMap() plus string env overrides (runtime/connections.go:339-355), and system connector config is likewise a structpb map, so every value is JSON-encodable. Hashing the JSON alone and letting a json.Marshal error surface would be simpler than a fallback that would print pointer addresses and produce a fresh cache key on every acquire.
  • In json_object mode the schema instruction is prepended as a separate system message ahead of whatever opts.Messages already contains (runtime/drivers/openai/openai.go:428; runtime/ai/ai.go:1326 passes the session's messages through unchanged, so Rill's own system prompt becomes the second system message). Providers whose chat templates accept only a single leading system message would reject that; merging the instruction into the existing system message would be more portable. This is a portability concern, not a verified failure against a specific provider.

The branch is 62 commits behind origin/main, but git merge-tree reports a clean merge and none of the intervening commits touch runtime/drivers/openai/ or runtime/connection_cache.go.

Comment on lines +51 to +72
### OpenAI-compatible APIs

The connector can also target APIs that implement the OpenAI chat completions protocol. Configure the provider's URL and model on the connector. If the provider supports JSON mode but not OpenAI's JSON Schema response format, set `structured_output_mode` to `json_object`:

```yaml
type: connector
driver: openai
api_key: "{{ .env.PROVIDER_API_KEY }}"
base_url: https://llm.example.com/v1
model: example-model
structured_output_mode: json_object
```

For provider-specific request extensions, use the advanced `extra_body` map. Its values must be JSON-serializable, and it cannot override core request fields such as `model`, `messages`, `tools`, `response_format`, or streaming controls. For example, an OpenAI-compatible endpoint can receive a chat-template option as follows:

```yaml
extra_body:
chat_template_kwargs:
enable_thinking: false
```

These options belong to the connector, so different connectors in the same Rill process can use different provider behavior.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

structured_output_mode and extra_body are not declared in the OpenAI block of runtime/parser/schema/project.schema.yaml, which this PR does not touch. That block generates docs/docs/reference/project-files/connectors.md through cli/cmd/docs/generate_project.go:29,488 (make docs.generate), so the OpenAI connector reference this page links to for "additional configuration options" will not list either property, and runtime/ai/instructions/instructions.go:198 feeds the same schema to the AI assistant, which will keep reporting that these keys do not exist on an openai connector. Nothing fails at runtime: runtime/parser/parse_connector.go:16 captures connector properties with mapstructure:",remain" and never validates them against the schema. main has since reworked that block, so the two properties (and ideally the extra_body example) need to go on top of its current version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area:Connectors Size:M Medium change: 100-499 lines Type:Feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants