metal-kompanion/docs/tool-calling-without-native...

76 lines
2.7 KiB
Markdown

# Tool Calling Without Native Support (Happy-Code Compatibility)
When models lack built-in tool/function calling, we can still get reliable tool use via a **protocol-in-prompt** approach plus a thin runtime.
## 1) JSON Tool Protocol (deterministic)
Model must respond with a single JSON object, no prose.
```json
{
"thought": "<very short planning note>",
"action": {
"tool": "<tool_name>",
"args": { }
}
}
```
- If more steps are needed, the runtime feeds the tool's JSON result back as the next user message with role=tool.
- The model must then either emit another action or finish with:
```json
{
"final": { "content": { } }
}
```
### Guardrails
- Reject any output that isn't valid JSON or that contains extra text.
- Cap thought to ~200 chars.
- Disallow calling tools not in the registry.
## 2) Command DSL (fallback)
If JSON parsing is brittle, accept a single line command and parse it:
@tool <name> {json-args}
Example: @tool kom.memory.v1.search_memory {"query":{"text":"embedding model"}}
## 3) Prompt Template (drop-in)
Use this system message for happy-code/claude-code sessions:
You are a coding assistant that can call tools via a JSON protocol. Available tools (names & schema will be provided). Always reply with a single JSON object. No markdown. No commentary. Use this schema: { "thought": string (short), "action": { "tool": string, "args": object } } OR { "final": { "content": any } }. If a tool result is needed, emit action. If done, emit final. Never invent tool names or fields.
## 4) Minimal Runtime (pseudocode)
while True:
msg = llm(messages)
data = json.loads(msg)
if 'action' in data:
tool = registry[data['action']['tool']]
result = tool(**data['action']['args'])
messages.append({"role":"tool","name":tool.name,"content":json.dumps(result)})
continue
elif 'final' in data:
return data['final']['content']
else:
error("Invalid protocol")
## 5) MCP Integration
- Map registry to MCP tools (e.g., kom.memory.v1.*).
- Provide each tool's JSON Schema to the model in the system message (strict).
## 6) Testing Checklist
- Invalid JSON → reject → ask to resend.
- Unknown tool → reject.
- Args mismatch → show schema snippet, ask to correct.
- Multi-step flows → verify tool result is consumed in next turn.
## 7) Example Session
System: (template above + list of tools & schemas)
User: Save this note: "Embedding model comparison takeaways" into project:metal
Assistant:
{"thought":"need to upsert note","action":{"tool":"kom.memory.v1.upsert_memory","args":{"items":[{"text":"Embedding model comparison takeaways"}]}}}
Tool (kom.memory.v1.upsert_memory): { "upserted": 1 }
Assistant:
{"final":{"content":{"status":"ok","upserted":1}}}