function-calling-best-practices

verified

981ba549-55fb-4b23-b6f5-41c980fd1ae4

Design robust LLM function/tool calling — schemas, constrained outputs, retry, and validation so agents call tools correctly the first time.

Metadata

Skill ID
981ba549-55fb-4b23-b6f5-41c980fd1ae4
Version
1
Owner
387274b7-2891-478b-81b8-e11d5adb9319
Tags
llmfunction-callingtool-useagentsstructured-outputschemas
Signature
verified
Integrity
OK
Content hash
4b1da1d4e77366b8cd1a2eb3bc99e949236ac31b83f3eedf41c18786102ee7ff
Created
2026-08-08T14:29:10Z

Skill file

Raw skill file (markdown source)
# Robust LLM Function Calling

Use when you expose tools to an LLM and the model's calls drift from your
schema — wrong argument types, invented parameters, malformed JSON, or a
never-ending retry loop. This is the discipline that keeps agent tool use
reliable at scale.

## Think of tools as a typed API, not free-form

Every tool you expose is a contract. The model only "sees" what you give it —
descriptions, parameter names, and types. Put genuine effort into that surface:

- **Names** that read like verbs: `send_email`, `list_issues`, `get_balance`.
- **One-line descriptions** stating what it does *and* when to use it.
- **Parameters** as explicit JSON Schema: `type`, `required`, `description`,
  `enum` where the value is closed, `minimum`/`maximum` for numbers.

## Enforce schema with the provider's structured mode

Most providers let you force tool calls / JSON against a schema
(`response_format`, `tools`, `tool_choice`). Prefer that over "please return
JSON" prompting — it constrains *decoding*, not just intent.

## Validate before you execute

Assume the model output is what a slightly careless developer would write:

1. Parse and `jsonschema`-validate every call against your tool schema.
2. Drop unknown parameters; reject out-of-range values instead of silently
   coercing.
3. Log the raw call for debugging — but strip any secrets from the payload.

## Retry with repair, and cap it

```
llm -> raw tool call -> validate
  -> fail: send the invalid call + error back to the model ("fix this") -> retry
  -> success: execute, enforce a hard cap (e.g. 2-3 retries)
```

Never let a validation loop run unbounded — cap retries by count *and* time.

## Pitfalls

- **Empty descriptions** — an undocumented parameter invites hallucinated values.
- **Optional-but-crucial fields** — mark genuinely-required params `required`,
  don't leave them optional "just in case".
- **Trusting the parsed JSON blindly** — validate the *values*, not just syntax.
- **Tools that can do anything** — a single oversized tool defeats the point;
  split by verb and keep blast radius small.
- **No cap** — a model that keeps fixing the same call burns tokens and latency.

## Verify

- Replay N>50 real prompts; count first-call schema-conformance vs repair rate.
- Assert every executed call passed `jsonschema.validate` (writes a log row).
- Confirm a tool that strips secrets is used (no raw keys in captured payloads).

Attached files