Skip to content

Commit eca802a

Browse files
authored
fix(agent): move mip_opt_out field to root level of SettingsOptions (#561)
The mip_opt_out field was incorrectly placed inside the agent object, but according to the Deepgram API specification, it should be at the root level of the Settings message payload. This was causing the API to return: 'Error parsing client message. Check the agent.mip_opt_out field against the API spec.' - Moved mip_opt_out from Agent class to SettingsOptions class - Updated all unit tests to reference the new location - Verified serialization now matches API spec: mip_opt_out at $message.payload#/mip_opt_out
1 parent d605248 commit eca802a

File tree

3 files changed

+50
-62
lines changed

3 files changed

+50
-62
lines changed

deepgram/clients/agent/v1/websocket/options.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,6 @@ class Agent(BaseResponse):
271271
greeting: Optional[str] = field(
272272
default=None, metadata=dataclass_config(exclude=lambda f: f is None)
273273
)
274-
mip_opt_out: Optional[bool] = field(
275-
default=False, metadata=dataclass_config(exclude=lambda f: f is None)
276-
)
277274
tags: Optional[List[str]] = field(
278275
default=None, metadata=dataclass_config(exclude=lambda f: f is None)
279276
)
@@ -355,6 +352,9 @@ class SettingsOptions(BaseResponse):
355352
type: str = str(AgentWebSocketEvents.Settings)
356353
audio: Audio = field(default_factory=Audio)
357354
agent: Agent = field(default_factory=Agent)
355+
mip_opt_out: Optional[bool] = field(
356+
default=False, metadata=dataclass_config(exclude=lambda f: f is None)
357+
)
358358

359359
def __getitem__(self, key):
360360
_dict = self.to_dict()

tests/unit_test/test_unit_agent_mip_opt_out.py

Lines changed: 43 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,28 @@
1111

1212

1313
class TestAgentMipOptOut:
14-
"""Unit tests for mip_opt_out agent setting"""
14+
"""Unit tests for mip_opt_out setting at the root level of SettingsOptions"""
1515

1616
def test_default_mip_opt_out_value(self):
1717
"""Test that mip_opt_out defaults to False"""
1818
options = SettingsOptions()
1919

20-
# Default should be False
21-
assert options.agent.mip_opt_out == False
22-
23-
# Verify it's accessible through the agent directly
24-
agent = Agent()
25-
assert agent.mip_opt_out == False
20+
# Default should be False at root level
21+
assert options.mip_opt_out == False
2622

2723
def test_set_mip_opt_out_true(self):
2824
"""Test setting mip_opt_out to True"""
2925
options = SettingsOptions()
30-
options.agent.mip_opt_out = True
26+
options.mip_opt_out = True
3127

32-
assert options.agent.mip_opt_out == True
28+
assert options.mip_opt_out == True
3329

3430
def test_set_mip_opt_out_false_explicitly(self):
3531
"""Test explicitly setting mip_opt_out to False"""
3632
options = SettingsOptions()
37-
options.agent.mip_opt_out = False
33+
options.mip_opt_out = False
3834

39-
assert options.agent.mip_opt_out == False
35+
assert options.mip_opt_out == False
4036

4137
def test_mip_opt_out_serialization_default(self):
4238
"""Test that mip_opt_out with default value is excluded from serialization"""
@@ -47,57 +43,55 @@ def test_mip_opt_out_serialization_default(self):
4743

4844
# With default False and exclude=lambda f: f is None metadata,
4945
# the field should be excluded from serialization when it's False/default
50-
# But let's verify the structure exists
51-
assert "agent" in result
52-
# The default exclude behavior might not serialize False values, let's test both cases
46+
# mip_opt_out should not be in the root level when it's the default value
47+
assert "mip_opt_out" not in result or result.get(
48+
"mip_opt_out") == False
5349

5450
def test_mip_opt_out_serialization_true(self):
5551
"""Test that mip_opt_out=True is included in serialization"""
5652
options = SettingsOptions()
57-
options.agent.mip_opt_out = True
53+
options.mip_opt_out = True
5854

5955
result = options.to_dict()
6056
json_str = options.to_json()
6157
parsed_json = json.loads(json_str)
6258

63-
# Should be included when True
64-
assert result["agent"]["mip_opt_out"] == True
65-
assert parsed_json["agent"]["mip_opt_out"] == True
59+
# Should be included at root level when True
60+
assert result["mip_opt_out"] == True
61+
assert parsed_json["mip_opt_out"] == True
6662

6763
def test_mip_opt_out_serialization_false_explicit(self):
6864
"""Test that mip_opt_out=False (explicit) behavior in serialization"""
6965
options = SettingsOptions()
70-
options.agent.mip_opt_out = False
66+
options.mip_opt_out = False
7167

7268
result = options.to_dict()
7369
json_str = options.to_json()
7470

7571
# The field might be excluded due to dataclass_config exclude logic
7672
# Let's verify the actual behavior
77-
if "mip_opt_out" in result.get("agent", {}):
78-
assert result["agent"]["mip_opt_out"] == False
73+
if "mip_opt_out" in result:
74+
assert result["mip_opt_out"] == False
7975

8076
def test_mip_opt_out_deserialization(self):
8177
"""Test deserializing mip_opt_out from dict"""
82-
# Test with True value
78+
# Test with True value at root level
8379
data_true = {
84-
"agent": {
85-
"mip_opt_out": True
86-
}
80+
"mip_opt_out": True,
81+
"agent": {}
8782
}
8883

8984
options_true = SettingsOptions.from_dict(data_true)
90-
assert options_true.agent.mip_opt_out == True
85+
assert options_true.mip_opt_out == True
9186

92-
# Test with False value
87+
# Test with False value at root level
9388
data_false = {
94-
"agent": {
95-
"mip_opt_out": False
96-
}
89+
"mip_opt_out": False,
90+
"agent": {}
9791
}
9892

9993
options_false = SettingsOptions.from_dict(data_false)
100-
assert options_false.agent.mip_opt_out == False
94+
assert options_false.mip_opt_out == False
10195

10296
def test_mip_opt_out_deserialization_missing(self):
10397
"""Test deserializing when mip_opt_out is not present (should default to False)"""
@@ -108,64 +102,58 @@ def test_mip_opt_out_deserialization_missing(self):
108102
}
109103

110104
options = SettingsOptions.from_dict(data)
111-
assert options.agent.mip_opt_out == False
105+
assert options.mip_opt_out == False
112106

113107
def test_mip_opt_out_round_trip(self):
114108
"""Test serialization and deserialization round-trip"""
115109
# Test with True
116110
original_true = SettingsOptions()
117-
original_true.agent.mip_opt_out = True
111+
original_true.mip_opt_out = True
118112

119113
serialized_true = original_true.to_dict()
120114
restored_true = SettingsOptions.from_dict(serialized_true)
121115

122-
assert restored_true.agent.mip_opt_out == True
116+
assert restored_true.mip_opt_out == True
123117

124118
# Test with False (if it gets serialized)
125119
original_false = SettingsOptions()
126-
original_false.agent.mip_opt_out = False
120+
original_false.mip_opt_out = False
127121

128122
serialized_false = original_false.to_dict()
129123
restored_false = SettingsOptions.from_dict(serialized_false)
130124

131-
assert restored_false.agent.mip_opt_out == False
125+
assert restored_false.mip_opt_out == False
132126

133-
def test_mip_opt_out_with_other_agent_settings(self):
134-
"""Test mip_opt_out works correctly with other agent settings"""
127+
def test_mip_opt_out_with_other_settings(self):
128+
"""Test mip_opt_out works correctly with other settings"""
135129
options = SettingsOptions()
136130
options.agent.language = "en"
137-
options.agent.mip_opt_out = True
131+
options.mip_opt_out = True
138132
options.agent.greeting = "Hello, I have opted out of MIP"
139133

140134
assert options.agent.language == "en"
141-
assert options.agent.mip_opt_out == True
135+
assert options.mip_opt_out == True
142136
assert options.agent.greeting == "Hello, I have opted out of MIP"
143137

144138
# Test serialization with multiple fields
145139
result = options.to_dict()
146140
assert result["agent"]["language"] == "en"
147-
assert result["agent"]["mip_opt_out"] == True
141+
assert result["mip_opt_out"] == True
148142
assert result["agent"]["greeting"] == "Hello, I have opted out of MIP"
149143

150144
def test_mip_opt_out_type_validation(self):
151145
"""Test that mip_opt_out accepts boolean values"""
152146
options = SettingsOptions()
153147

154148
# Should accept boolean values
155-
options.agent.mip_opt_out = True
156-
assert options.agent.mip_opt_out == True
149+
options.mip_opt_out = True
150+
assert options.mip_opt_out == True
157151

158-
options.agent.mip_opt_out = False
159-
assert options.agent.mip_opt_out == False
152+
options.mip_opt_out = False
153+
assert options.mip_opt_out == False
160154

161-
def test_agent_direct_instantiation(self):
162-
"""Test mip_opt_out when creating Agent directly"""
155+
def test_legacy_agent_mip_opt_out_removed(self):
156+
"""Test that mip_opt_out is no longer on the Agent class"""
163157
agent = Agent()
164-
assert agent.mip_opt_out == False
165-
166-
agent.mip_opt_out = True
167-
assert agent.mip_opt_out == True
168-
169-
# Test serialization of direct Agent instance
170-
result = agent.to_dict()
171-
assert result["mip_opt_out"] == True
158+
# mip_opt_out should not exist on Agent anymore
159+
assert not hasattr(agent, 'mip_opt_out')

tests/unit_test/test_unit_agent_tags.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,19 @@ def test_tags_with_other_agent_settings(self):
162162
options.agent.language = "en"
163163
options.agent.tags = ["integration", "test"]
164164
options.agent.greeting = "Hello, this is a tagged conversation"
165-
options.agent.mip_opt_out = True
165+
options.mip_opt_out = True
166166

167167
assert options.agent.language == "en"
168168
assert options.agent.tags == ["integration", "test"]
169169
assert options.agent.greeting == "Hello, this is a tagged conversation"
170-
assert options.agent.mip_opt_out == True
170+
assert options.mip_opt_out == True
171171

172172
# Test serialization with multiple fields
173173
result = options.to_dict()
174174
assert result["agent"]["language"] == "en"
175175
assert result["agent"]["tags"] == ["integration", "test"]
176176
assert result["agent"]["greeting"] == "Hello, this is a tagged conversation"
177-
assert result["agent"]["mip_opt_out"] == True
177+
assert result["mip_opt_out"] == True
178178

179179
def test_tags_type_validation(self):
180180
"""Test that tags accepts list of strings"""
@@ -190,4 +190,4 @@ def test_tags_type_validation(self):
190190

191191
# Should accept None
192192
options.agent.tags = None
193-
assert options.agent.tags is None
193+
assert options.agent.tags is None

0 commit comments

Comments
 (0)