Skip to content

Commit 042be08

Browse files
authored
Merge pull request #61 from seymourtang/feat/openai-mllm
feat: update OpenAIRealtime WebSocket URL and add validation tests
2 parents fe61d5e + bf658f6 commit 042be08

4 files changed

Lines changed: 27 additions & 4 deletions

File tree

docs/reference/vendors.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ No constructor parameters. Use `FengmingSTT()`.
780780
|---|---|---|---|---|
781781
| `api_key` | `str` | Yes || OpenAI API key |
782782
| `model` | `str` | No | `None` | Model (e.g., `gpt-4o-realtime-preview`) |
783-
| `url` | `str` | No | `None` | Custom WebSocket URL |
783+
| `url` | `str` | No | `wss://api.openai.com/v1/realtime` | OpenAI Realtime WebSocket URL |
784784
| `greeting_message` | `str` | No | `None` | Greeting message |
785785
| `failure_message` | `str` | No | `None` | Message played when the model call fails |
786786
| `input_modalities` | `List[str]` | No | `None` | Input modalities |

src/agora_agent/agentkit/vendors/mllm.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ class OpenAIRealtime(BaseMLLM):
1616
voice: Optional[str] = Field(default=None, description="Voice identifier")
1717
instructions: Optional[str] = Field(default=None, description="System instructions")
1818
input_audio_transcription: Optional[Dict[str, Any]] = Field(default=None, description="Audio transcription settings")
19-
url: Optional[str] = Field(default=None, description="WebSocket URL")
19+
url: str = Field(
20+
default="wss://api.openai.com/v1/realtime",
21+
description="OpenAI Realtime WebSocket URL",
22+
)
2023
greeting_message: Optional[str] = Field(default=None, description="Agent greeting message")
2124
input_modalities: Optional[List[str]] = Field(default=None, description="Input modalities")
2225
output_modalities: Optional[List[str]] = Field(default=None, description="Output modalities")
@@ -29,10 +32,9 @@ def to_config(self) -> Dict[str, Any]:
2932
config: Dict[str, Any] = {
3033
"vendor": "openai",
3134
"api_key": self.api_key,
35+
"url": self.url,
3236
}
3337

34-
if self.url is not None:
35-
config["url"] = self.url
3638
if (
3739
self.model is not None
3840
or self.params is not None

tests/custom/test_agentkit_vendors.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ def test_xai_grok_serializes_v27_shape_without_style():
3838
assert "style" not in config
3939

4040

41+
def test_openai_realtime_uses_default_url_when_omitted():
42+
config = OpenAIRealtime(api_key="openai-key").to_config()
43+
44+
assert config["url"] == "wss://api.openai.com/v1/realtime"
45+
46+
47+
def test_openai_realtime_preserves_custom_url():
48+
config = OpenAIRealtime(
49+
api_key="openai-key",
50+
url="wss://openai.example.com/v1/realtime",
51+
).to_config()
52+
53+
assert config["url"] == "wss://openai.example.com/v1/realtime"
54+
55+
56+
def test_openai_realtime_rejects_none_url():
57+
with pytest.raises(ValidationError):
58+
OpenAIRealtime(api_key="openai-key", url=None)
59+
60+
4161
def test_xai_grok_emits_params_even_when_empty():
4262
assert XaiGrok(api_key="xai-key").to_config()["params"] == {}
4363

tests/custom/test_request_body.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,7 @@ def test_byok_openai_realtime_mllm_params() -> None:
12651265
props = build_properties(agent)
12661266
assert props["mllm"]["vendor"] == "openai"
12671267
assert props["mllm"]["api_key"] == "realtime-key"
1268+
assert props["mllm"]["url"] == "wss://api.openai.com/v1/realtime"
12681269
assert props["mllm"]["params"]["model"] == "gpt-4o-realtime-preview"
12691270
assert props["mllm"]["params"]["voice"] == "coral"
12701271

0 commit comments

Comments
 (0)