autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
137
skills/conol-automation/references/conol-tool-use.md
Normal file
137
skills/conol-automation/references/conol-tool-use.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Conol.ai Tool Use Protocol
|
||||
|
||||
Gateway v6.0+ supports OpenAI-compatible tool calling through conol.ai's SSE API.
|
||||
|
||||
## Sending Tools to Conol.ai
|
||||
|
||||
Tools are passed in the session creation body as an Anthropic-format array:
|
||||
|
||||
```python
|
||||
session_body = {
|
||||
"source": {"type": "home"},
|
||||
"messages": conol_msgs,
|
||||
"timezone": "Europe/Kyiv",
|
||||
"agentModel": model,
|
||||
"agentEffort": "low",
|
||||
"tools": [
|
||||
{
|
||||
"name": "get_weather",
|
||||
"description": "Get current weather for a city",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {"city": {"type": "string"}},
|
||||
"required": ["city"],
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Both Anthropic-format (`name`, `input_schema`) and OpenAI-format (`type: "function"`, `function: {name, parameters}`) are accepted by conol.ai. The gateway converts OpenAI format to Anthropic before sending.
|
||||
|
||||
## Receiving Tool Calls from SSE
|
||||
|
||||
Conol.ai emits tool calls as SSE `history_delta` events with `tool_call` log entries:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "history_delta",
|
||||
"stages": [{
|
||||
"id": "...",
|
||||
"logs": [{
|
||||
"role": "assistant",
|
||||
"type": "tool_call",
|
||||
"content": [{
|
||||
"name": "WebSearch",
|
||||
"type": "tool_call",
|
||||
"input": {"query": "Paris weather"},
|
||||
"result": [{"text": "83°F, Overcast..."}]
|
||||
}]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
Key fields:
|
||||
- `name` — tool name (string)
|
||||
- `input` — JSON arguments (dict)
|
||||
- `result` — optional: array of `{"text": "..."}` objects with tool output
|
||||
|
||||
## Converting to OpenAI Format
|
||||
|
||||
```python
|
||||
def conol_to_openai_tool_calls(events):
|
||||
tool_calls = []
|
||||
for ev in events:
|
||||
if ev.tool_name:
|
||||
tool_calls.append({
|
||||
"id": f"call_{uuid.uuid4().hex[:8]}",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": ev.tool_name,
|
||||
"arguments": json.dumps(ev.tool_input, ensure_ascii=False),
|
||||
},
|
||||
})
|
||||
return tool_calls
|
||||
```
|
||||
|
||||
## Built-in Tools (Auto-called by conol.ai)
|
||||
|
||||
Conol.ai models have built-in tools that fire automatically even when no user tools are provided:
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| `WebSearch` | Web search via Exa.ai |
|
||||
| `Fetch` | Fetch URL content with prompt |
|
||||
| `SetIntention` | Internal meta-tool for task routing |
|
||||
| `WriteNote` | Create Obsidian-style notes |
|
||||
| `ReadNote` | Read persisted notes |
|
||||
|
||||
These appear in SSE as `tool_call` logs alongside any user-provided tools.
|
||||
|
||||
## Streaming Tool Calls
|
||||
|
||||
In streaming mode, tool calls are emitted as SSE chunks with `delta.tool_calls[]`:
|
||||
|
||||
```json
|
||||
{
|
||||
"object": "chat.completion.chunk",
|
||||
"choices": [{
|
||||
"delta": {"tool_calls": [{"id": "call_abc", "type": "function", "function": {"name": "WebSearch", "arguments": "{\"query\":\"...\"}"}}]},
|
||||
"finish_reason": null
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
Then final chunk with `finish_reason: "tool_calls"` or `"stop"`.
|
||||
|
||||
## Tool Result Loop (Tool → Model → Response)
|
||||
|
||||
To continue a conversation after tool calls, send tool results back as messages with `role: "tool"`:
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "gpt-5.6-luna",
|
||||
"messages": [
|
||||
{"role": "user", "content": "Weather in Paris?"},
|
||||
{"role": "assistant", "content": null, "tool_calls": [{"id": "call_1", "function": {"name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}}]},
|
||||
{"role": "tool", "tool_call_id": "call_1", "content": "83°F, Overcast"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The gateway converts `role: "tool"` messages to text: `[Tool result #call_1]: 83°F, Overcast`.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
### Duplicate Tool Calls
|
||||
Conol.ai sometimes emits duplicate `tool_call` events in the SSE stream (same name, same arguments, different stage IDs). The gateway currently returns all of them. For production use, deduplicate by `(name, json.dumps(input))` key.
|
||||
|
||||
### Tool + Text in Same Response
|
||||
Conol.ai models may return BOTH text content AND tool calls in the same response. OpenAI convention is `content: null` when tool_calls are present. The gateway currently returns both — downstream clients expecting strict OpenAI protocol may need `content: null` when `tool_calls` is non-empty.
|
||||
|
||||
### Tool Choice
|
||||
`tool_choice: "auto"/"none"/"required"` is passed but conol.ai does not enforce strict tool choice — it always has its built-in tools available. For `tool_choice: "none"`, filter tool calls out in the gateway.
|
||||
|
||||
### Streaming + Tool Calls
|
||||
When streaming with tools, conol.ai sends thinking text first, then tool calls, then final text. The gateway collects all events and emits tool calls first, then text. This causes a delay before the first chunk — the full response must arrive before streaming begins. Future improvement: buffer and emit as events arrive.
|
||||
Reference in New Issue
Block a user