mirror of
https://github.com/usestrix/strix.git
synced 2026-11-04 07:27:16 +00:00
fix: tolerate string-encoded skills param for LLM provider compatibility
Some LLM providers (e.g. qwen3.7-max via DashScope OpenAI-compatible endpoint) serialize array-typed function call parameters as JSON-encoded strings instead of native JSON arrays. This causes Pydantic validation to reject the skills parameter before the function body executes, making every create_agent and load_skill call fail. Changes: - Widen skills type annotation: list[str] -> str | list[str] - Add strict_mode=False to @function_tool decorator - Parse string inputs in function body (json.loads with comma-split fallback) Tested with qwen3.7-max: create_agent successfully spawns child agents that execute 23+ exec_command calls for SQL injection testing. Closes #770
This commit is contained in:
parent
40f4e67320
commit
730230effb
2 changed files with 18 additions and 4 deletions
|
|
@ -350,13 +350,13 @@ async def wait_for_message( # noqa: PLR0911
|
|||
)
|
||||
|
||||
|
||||
@function_tool(timeout=120)
|
||||
@function_tool(timeout=120, strict_mode=False)
|
||||
async def create_agent(
|
||||
ctx: RunContextWrapper,
|
||||
name: str,
|
||||
task: str,
|
||||
inherit_context: bool = True,
|
||||
skills: list[str] | None = None,
|
||||
skills: str | list[str] | None = None,
|
||||
) -> str:
|
||||
"""Spawn a specialist child agent to run in parallel.
|
||||
|
||||
|
|
@ -419,6 +419,12 @@ async def create_agent(
|
|||
default=str,
|
||||
)
|
||||
|
||||
# Tolerate LLM providers that pass array params as JSON-encoded strings
|
||||
if isinstance(skills, str):
|
||||
try:
|
||||
skills = json.loads(skills)
|
||||
except json.JSONDecodeError:
|
||||
skills = [s.strip() for s in skills.split(",") if s.strip()]
|
||||
skill_list = list(skills or [])
|
||||
skill_error = validate_requested_skills(skill_list)
|
||||
if skill_error:
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from agents import RunContextWrapper, function_tool
|
||||
|
||||
from strix.skills import load_skills, validate_requested_skills
|
||||
|
||||
|
||||
@function_tool(timeout=10)
|
||||
async def load_skill(ctx: RunContextWrapper, skills: list[str]) -> str:
|
||||
@function_tool(timeout=10, strict_mode=False)
|
||||
async def load_skill(ctx: RunContextWrapper, skills: str | list[str]) -> str:
|
||||
"""Return the markdown body of one or more skills as reference material.
|
||||
|
||||
Use this when you need exact syntax / workflow / payload guidance
|
||||
|
|
@ -25,6 +27,12 @@ async def load_skill(ctx: RunContextWrapper, skills: list[str]) -> str:
|
|||
``strix/skills/<category>/<name>.md``.
|
||||
"""
|
||||
del ctx
|
||||
# Tolerate LLM providers that pass array params as JSON-encoded strings
|
||||
if isinstance(skills, str):
|
||||
try:
|
||||
skills = json.loads(skills)
|
||||
except json.JSONDecodeError:
|
||||
skills = [s.strip() for s in skills.split(",") if s.strip()]
|
||||
requested = list(skills or [])
|
||||
err = validate_requested_skills(requested)
|
||||
if err:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue