When exposing APIs/tools to an LLM, treat docstrings, parameter semantics, and output size as an interface contract: make it unambiguous, match callable tool names exactly, structure “what to do” for reliable parsing, and cap context/token growth.
Apply these rules: 1) Guidance must match the callable surface
action param), represent the action→required-parameters mapping in a compact, JSON-like block inside the docstring.
4) Keep model/schema field descriptions minimalExample (structured dispatcher + parameter contract):
def rum(action: str, page_url: str | None = None, **kwargs) -> str:
"""CloudWatch RUM tools.
Actions:
{
"errors": {"required": [], "optional": ["page_url", "group_by"]},
"performance_navigation": {"required": [], "optional": ["page_url"]}
}
Parameter semantics:
- page_url: if provided, filters by metadata.pageId.
Notes:
- session_detail defaults to limit=100; pass a higher `limit` only if you need full replay.
"""
...
Example (token-safe default limit):
def session_detail_query(session_id: str, limit: int = 100) -> str:
return f"""fields @timestamp, event_type, metadata.pageId, event_details.duration
| filter user_details.sessionId = "{session_id}"
| sort @timestamp asc
| limit {limit}"""