From d8559ca133252cd30e6c0e11577faa8d91d3c830 Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 28 Jun 2026 14:18:37 -0300 Subject: [PATCH] Make OpenAPI tool names provider-safe --- agent.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/agent.py b/agent.py index 1b31fb2..df45617 100644 --- a/agent.py +++ b/agent.py @@ -1,6 +1,7 @@ from __future__ import annotations import base64 +import hashlib import json import re from pathlib import Path @@ -38,6 +39,34 @@ PATH_PARAMETER_RE = re.compile(r"{([^}/]+)}") SOURCE_ROOT = Path(globals().get("__file__", "agent.py")).resolve().parent SOURCE_SKILLS_DIR = SOURCE_ROOT / "skills" RUNTIME_SKILLS_DIR = ".deepagents/openapi-skills/" +MAX_OPENAI_TOOL_NAME_LENGTH = 64 + + +def _openai_safe_tool_name(name: str, used: set[str]) -> str: + safe = re.sub(r"[^a-zA-Z0-9_-]+", "_", name).strip("_") or "operation" + if len(safe) > MAX_OPENAI_TOOL_NAME_LENGTH: + digest = hashlib.sha1(safe.encode("utf-8")).hexdigest()[:10] + prefix = safe[: MAX_OPENAI_TOOL_NAME_LENGTH - len(digest) - 1].rstrip("_-") + safe = f"{prefix or 'operation'}_{digest}" + candidate = safe + index = 2 + while candidate in used: + suffix = f"_{index}" + candidate = safe[: MAX_OPENAI_TOOL_NAME_LENGTH - len(suffix)].rstrip("_-") + suffix + index += 1 + used.add(candidate) + return candidate + + +def _normalize_operation_tool_names() -> None: + used: set[str] = set() + for operation_id, operation in OPERATIONS.items(): + original = str(operation.get("skill_name") or operation_id) + operation["original_skill_name"] = original + operation["skill_name"] = _openai_safe_tool_name(original, used) + + +_normalize_operation_tool_names() class OperationInput(BaseModel): @@ -241,6 +270,7 @@ class Learnhouse(A2AAgent): ) if operation.get("request_body") is not None: parts.append("Accepts a JSON request body.") + parts.append(f"Operation ID: {operation.get('operation_id') or operation.get('original_skill_name')}") return "\n".join(part for part in parts if part) async def _request( @@ -287,6 +317,7 @@ class Learnhouse(A2AAgent): "ok": False, "status_code": response.status_code, "operation_id": operation_id, + "tool_name": operation.get("skill_name"), "error": payload, } if response.status_code in {404, 405, 410, 422}: @@ -299,6 +330,7 @@ class Learnhouse(A2AAgent): "ok": True, "status_code": response.status_code, "operation_id": operation_id, + "tool_name": operation.get("skill_name"), "result": payload, }