I am getting this error with groq - livekit.agents...
# ask-ai
q
I am getting this error with groq - livekit.agents._exceptions.APIStatusError: Error code: 400 - {'error': {'message': "invalid JSON schema for tool end_call, tools[2].function.parameters: 'required' present but 'properties' is missing", 'type': 'invalid_request_error', 'param': 'tool end_call, tools[2].function.parameters'}} (status_code=400, request_id=req_01kkhgfnjvfxj9mrjp0der44sp, body={'message': "invalid JSON schema for tool end_call, tools[2].function.parameters: 'required' present but 'properties' is missing", 'type': 'invalid_request_error', 'param': 'tool end_call, tools[2].function.parameters'}, retryable=True)
t
Thanks for reaching out, Harsh. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — that error means the JSON schema for your tool
end_call
includes a
required
list but does not define a
properties
object. JSON Schema validation requires that if you list required fields, you must also declare those fields in
properties
. What I’m responding to: the error you posted: livekit.agents._exceptions.APIStatusError: ... "invalid JSON schema for tool end_call, tools[2].function.parameters: 'required' present but 'properties' is missing" What you can do (quick fixes) • If the tool expects arguments: add a
properties
object that defines each required field and keep
required
. Example:
Copy code
"parameters": {
  "type": "object",
  "properties": {
    "reason": {
      "type": "string",
      "description": "The reason for ending the call"
    }
  },
  "required": ["reason"]
}
• If the tool should take no arguments: remove
required
(and you can leave
properties
empty) — for example:
Copy code
"parameters": {
  "type": "object",
  "properties": {}
}
If you’re using a decorator like
@function_tool
with
raw_schema
, ensure
parameters
follows the same structure (include
properties
when you list
required
). To help further, please share one of these: • The exact `parameters`/raw schema you currently use for
end_call
, or • The code snippet where you define the tool (the
@function_tool
block or equivalent). I can then point out the precise change to make or provide a corrected snippet. Sources: Function tool definition | LiveKit Documentation
q
how should i change the function call then - This is my end call function -
Copy code
@function_tool()
async def end_call(self,
                   ctx: RunContext):
    """Called when the agents has collected all information and is ready to end the call."""
    <http://log.info|log.info>(f"[{self.agent_name}][correlation_id: {self.room_name}]: Ending the call")
    # await self.session.say(text=f"{message}")
    await ctx.wait_for_playout()
    await asyncio.sleep(0.5)
    self.disconnectedBy = 'Bot'
    await self.hangup()
t
Thanks — I can see your
end_call
implementation is an argument-less async function, which means your tool schema should either declare no required parameters or include an empty
properties
object. The JSON schema validation error happened because
required
was present in the tool definition but
properties
was missing. Two ways to fix this depending on how you register the tool: 1) If you register the tool with no parameters (recommended here) • Remove any
required
from the tool's
parameters
schema and set
properties
to an empty object. Example using
raw_schema
(or the decorator that accepts schema):
Copy code
@function_tool(raw_schema={
  "name": "end_call",
  "description": "End the current call.",
  "parameters": {
    "type": "object",
    "properties": {}
  }
})
async def end_call(self, ctx: RunContext):
    # your existing implementation
    <http://log.info|log.info>(f"[{self.agent_name}][correlation_id: {self.room_name}]: Ending the call")
    await ctx.wait_for_playout()
    await asyncio.sleep(0.5)
    self.disconnectedBy = 'Bot'
    await self.hangup()
2) If you want the tool to accept parameters (for example a
reason
) • Define
properties
and
required
to match the expected fields. Example:
Copy code
@function_tool(raw_schema={
  "name": "end_call",
  "description": "End the current call.",
  "parameters": {
    "type": "object",
    "properties": {
      "reason": {
        "type": "string",
        "description": "The reason for ending the call"
      }
    },
    "required": ["reason"]
  }
})
async def end_call(self, ctx: RunContext, reason: str = None):
    <http://log.info|log.info>(f"[{self.agent_name}][correlation_id: {self.room_name}]: Ending the call: {reason}")
    await ctx.wait_for_playout()
    await asyncio.sleep(0.5)
    self.disconnectedBy = 'Bot'
    await self.hangup()
Which option fits you? • If
end_call
should have no arguments, use option 1. • If you need arguments (like
reason
), use option 2 and adjust the function signature to accept them. If you share how you currently register the tool (the decorator call or the tool list where
end_call
is defined), I’ll provide the exact corrected snippet to paste in.
q
So if i have to use any of the Open AI models, I have to follow this way for defining function_tools
t
You're on the right track — OpenAI models require function definitions to include a valid JSON schema when you register them for function calling. That means when you expose a Python function as a
function_tool
(or otherwise register it as a callable tool for the model), its
parameters
schema must be a valid JSON Schema object. Concretely: • If you include a
required
array, you must also include a
properties
object that lists the required fields. • If the function takes no arguments, omit
required
and either include an empty
properties
object or no
parameters
block at all (depending on your tool registration method). What this looks like in practice • No-argument tool (recommended for your current
end_call
):
Copy code
@function_tool(raw_schema={
  "name": "end_call",
  "description": "End the current call.",
  "parameters": {
    "type": "object",
    "properties": {}
  }
})
async def end_call(self, ctx: RunContext):
    # your implementation
• Tool with arguments (only if you need them):
Copy code
@function_tool(raw_schema={
  "name": "end_call",
  "description": "End the current call.",
  "parameters": {
    "type": "object",
    "properties": {
      "reason": {
        "type": "string",
        "description": "The reason for ending the call"
      }
    },
    "required": ["reason"]
  }
})
async def end_call(self, ctx: RunContext, reason: str):
    # handle reason
Quick checklist to avoid the JSON schema error you saw • Do not list fields in
required
unless they are defined under
properties
. • Ensure
parameters
is an object with
"type": "object"
when using properties/required. • If you register tools in a list (not via decorator), check that each tool’s
function.parameters
follows the same rules. If you want, paste the decorator or the tool registration snippet you currently use (the
@function_tool(...)
call or the tool list) and I’ll give the exact corrected schema to paste in.