fix: address audit findings — SDK plumbing, TUI bus, dead code
Critical fixes: - ``StrixOrchestrationHooks.on_agent_start`` now finds the ``CaidoCapability`` via ``ctx.context['caido_capability']`` instead of ``agent.capabilities`` (we use plain ``Agent``, not ``SandboxAgent``, so the latter never existed). The session manager's bundle already exposes the capability; ``run_strix_scan`` threads it through ``make_agent_context`` and ``create_agent`` forwards it to children. - ``run_strix_scan`` registers the ``StrixTracingProcessor`` with the SDK's tracing provider via ``add_trace_processor`` so SDK trace spans hit ``run_dir/events.jsonl`` (was previously a parallel stream the SDK ignored). - ``on_llm_end`` now writes to ``Tracer.record_llm_usage`` in addition to ``bus.record_usage`` so the CLI/TUI stats panel sees real numbers instead of zeros. - ``run_strix_scan`` accepts an externally-built ``AgentMessageBus`` + an explicit ``model`` arg. The TUI pre-creates the bus so its stop and chat-input handlers can submit ``bus.send`` / ``bus.cancel_descendants`` coroutines onto the scan thread's loop via ``asyncio.run_coroutine_threadsafe`` — replacing the TODO-stub no-ops. - ``model`` config now propagates root → context → child agents in ``create_agent`` (was hardcoded fallback). Dead-code removal: - Deleted the ``load_skill`` tool entirely (host module, sandbox module, TUI renderer, tests). The legacy implementation reached into a global ``_agent_instances`` registry that no longer exists; the post-migration stub returned ``success=True`` without injecting anything — pure theater. Skills are still preloaded via the system prompt at scan-bring-up. - Dropped ``tenacity`` and ``xmltodict`` from ``[project.dependencies]`` — neither is imported anywhere post-migration. - Stripped the system prompt's "use the load_skill tool" lines. Tests: 278/278 passing. Removed two ``load_skill`` test cases and a ``test_tool_registration_modes::test_load_skill_import_...`` assertion that exercised the deleted module. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,6 @@ from .agents_graph import * # noqa: F403
|
||||
from .browser import * # noqa: F403
|
||||
from .file_edit import * # noqa: F403
|
||||
from .finish import * # noqa: F403
|
||||
from .load_skill import * # noqa: F403
|
||||
from .notes import * # noqa: F403
|
||||
from .proxy import * # noqa: F403
|
||||
from .python import * # noqa: F403
|
||||
|
||||
@@ -8,7 +8,6 @@ adapter object from the run context.
|
||||
|
||||
Used by:
|
||||
- ``tools/todo/tools.py``
|
||||
- ``tools/load_skill/tool.py``
|
||||
- ``tools/finish/tool.py``
|
||||
"""
|
||||
|
||||
|
||||
@@ -357,6 +357,7 @@ async def create_agent(
|
||||
sandbox_token=inner.get("sandbox_token"),
|
||||
tool_server_host_port=inner.get("tool_server_host_port"),
|
||||
caido_host_port=inner.get("caido_host_port"),
|
||||
caido_capability=inner.get("caido_capability"),
|
||||
agent_id=child_id,
|
||||
agent_name=name,
|
||||
parent_id=parent_id,
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
from .load_skill_actions import load_skill
|
||||
|
||||
|
||||
__all__ = ["load_skill"]
|
||||
@@ -1,58 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
from strix.tools.registry import register_tool
|
||||
|
||||
|
||||
@register_tool(sandbox_execution=False)
|
||||
def load_skill(agent_state: Any, skills: str) -> dict[str, Any]:
|
||||
try:
|
||||
from strix.skills import parse_skill_list, validate_requested_skills
|
||||
|
||||
requested_skills = parse_skill_list(skills)
|
||||
if not requested_skills:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "No skills provided. Pass one or more comma-separated skill names.",
|
||||
"requested_skills": [],
|
||||
}
|
||||
|
||||
validation_error = validate_requested_skills(requested_skills)
|
||||
if validation_error:
|
||||
return {
|
||||
"success": False,
|
||||
"error": validation_error,
|
||||
"requested_skills": requested_skills,
|
||||
"loaded_skills": [],
|
||||
}
|
||||
|
||||
# Runtime skill injection used to reach into the legacy
|
||||
# ``_agent_instances`` registry to mutate the running LLM's
|
||||
# active-skills list. The SDK harness owns the agent through
|
||||
# ``Runner.run`` and there's no equivalent reach-in API yet —
|
||||
# the model still gets a structured success response so it can
|
||||
# observe which skills it asked for, even if reload-on-the-fly
|
||||
# is a Phase 6 follow-up.
|
||||
newly_loaded = list(requested_skills)
|
||||
already_loaded: list[str] = []
|
||||
|
||||
except Exception as e: # noqa: BLE001
|
||||
fallback_requested_skills = (
|
||||
requested_skills
|
||||
if "requested_skills" in locals()
|
||||
else [s.strip() for s in skills.split(",") if s.strip()]
|
||||
)
|
||||
return {
|
||||
"success": False,
|
||||
"error": f"Failed to load skill(s): {e!s}",
|
||||
"requested_skills": fallback_requested_skills,
|
||||
"loaded_skills": [],
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"success": True,
|
||||
"requested_skills": requested_skills,
|
||||
"loaded_skills": requested_skills,
|
||||
"newly_loaded_skills": newly_loaded,
|
||||
"already_loaded_skills": already_loaded,
|
||||
"message": "Skills loaded into this agent prompt context.",
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<tools>
|
||||
<tool name="load_skill">
|
||||
<description>Dynamically load one or more skills into the current agent at runtime.
|
||||
|
||||
Use this when you need exact guidance right before acting (tool syntax, exploit workflow, or protocol details).
|
||||
This updates the current agent's prompt context immediately.</description>
|
||||
<details>Accepts one skill or a comma-separated skill bundle. Works for root agents and subagents.
|
||||
Examples:
|
||||
- Single skill: `xss`
|
||||
- Bundle: `sql_injection,business_logic`</details>
|
||||
<parameters>
|
||||
<parameter name="skills" type="string" required="true">
|
||||
<description>Comma-separated list of skills to use for the agent (MAXIMUM 5 skills allowed). Most agents should have at least one skill in order to be useful. Agents should be highly specialized - use 1-3 related skills; up to 5 for complex contexts. {{DYNAMIC_SKILLS_DESCRIPTION}}</description>
|
||||
</parameter>
|
||||
</parameters>
|
||||
<returns type="Dict[str, Any]">
|
||||
<description>Response containing: - success: Whether runtime loading succeeded - requested_skills: Skills requested - loaded_skills: Skills validated and applied - newly_loaded_skills: Skills newly injected into prompt - already_loaded_skills: Skills already present in prompt context</description>
|
||||
</returns>
|
||||
<examples>
|
||||
<function=load_skill>
|
||||
<parameter=skills>xss</parameter>
|
||||
</function>
|
||||
|
||||
<function=load_skill>
|
||||
<parameter=skills>sql_injection,business_logic</parameter>
|
||||
</function>
|
||||
|
||||
<function=load_skill>
|
||||
<parameter=skills>nmap,httpx</parameter>
|
||||
</function>
|
||||
</examples>
|
||||
</tool>
|
||||
</tools>
|
||||
@@ -1,46 +0,0 @@
|
||||
"""SDK function-tool wrapper for the legacy ``load_skill`` tool.
|
||||
|
||||
The legacy implementation reaches into ``_agent_instances`` (a global
|
||||
dict the legacy multi-agent orchestrator maintains) to find the running
|
||||
``Agent`` instance and call ``agent.llm.add_skills(...)``. That global
|
||||
goes away under the SDK migration — Phase 3 will replace it with a
|
||||
context-keyed registry, and this wrapper will be updated to read from
|
||||
that registry.
|
||||
|
||||
For Phase 2 we ship the wrapper as-is. The legacy function falls back
|
||||
to a clean error path when the agent instance lookup fails, so the
|
||||
tool degrades gracefully ("Could not find running agent instance...")
|
||||
until Phase 3 lands. That's better than crashing or stubbing out the
|
||||
tool entirely — the model still gets a structured error it can react to.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from agents import RunContextWrapper
|
||||
|
||||
from strix.tools._decorator import strix_tool
|
||||
from strix.tools._state_adapter import adapter_from_ctx
|
||||
from strix.tools.load_skill import load_skill_actions as _impl
|
||||
|
||||
|
||||
def _dump(result: dict[str, Any]) -> str:
|
||||
return json.dumps(result, ensure_ascii=False, default=str)
|
||||
|
||||
|
||||
@strix_tool(timeout=60)
|
||||
async def load_skill(ctx: RunContextWrapper, skills: str) -> str:
|
||||
"""Load one or more named skills into this agent's prompt context.
|
||||
|
||||
Args:
|
||||
skills: Comma-separated skill names (max 5). E.g.
|
||||
``"recon,xss,sqli"``. Skill discovery uses
|
||||
``strix.skills.parse_skill_list``.
|
||||
"""
|
||||
state = adapter_from_ctx(ctx)
|
||||
return _dump(
|
||||
await asyncio.to_thread(_impl.load_skill, agent_state=state, skills=skills),
|
||||
)
|
||||
Reference in New Issue
Block a user