0Pricing
AI Agents · Lesson

Returning Results to the Model

Format tool outputs as tool-role messages so the model can read them and continue the conversation.

Returning Results to the Model is a free AI Agents lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Agents learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Tool Result Message

After running a tool, you tell the model the outcome with a tool message:

messages.append({
    'role': 'tool',
    'tool_call_id': tool_call.id,    # MUST match the assistant's tool_call.id
    'content': json.dumps(result)
})

Content Should Be a String

OpenAI expects content to be a string. Serialize objects with json.dumps:

# Bad — will error
messages.append({'role': 'tool', 'tool_call_id': id, 'content': {'temp': 18}})

# Good
messages.append({'role': 'tool', 'tool_call_id': id, 'content': '{"temp": 18}'})

Anthropic Format

Anthropic uses a content block inside a user message:

messages.append({
    'role': 'user',
    'content': [{
        'type': 'tool_result',
        'tool_use_id': 'toolu_abc',
        'content': json.dumps(result)
    }]
})

Returning Errors

If the tool failed, return the error — don't pretend it succeeded. The model can recover:

try:
    result = run_tool(...)
    content = json.dumps({'ok': True, 'data': result})
except Exception as e:
    content = json.dumps({'ok': False, 'error': str(e)})

messages.append({'role': 'tool', 'tool_call_id': id, 'content': content})

Multi-Result Pattern

For parallel tool calls, append each result with its matching ID:

for tc in message.tool_calls:
    result = dispatch(tc)
    messages.append({
        'role': 'tool',
        'tool_call_id': tc.id,
        'content': json.dumps(result)
    })

Big Outputs: Summarise

If a tool returns 100KB of HTML, sending it all to the model wastes tokens and dilutes attention. Summarise or truncate first:

def truncate(text, max_chars=4000):
    if len(text) <= max_chars:
        return text
    return text[:max_chars] + f'\n...[truncated, {len(text)-max_chars} more chars]'

sample = "x" * 4500
result = truncate(sample, max_chars=50)
print(result)

Always-Same Schema

Even when results vary (success / error / not-found), keep the output schema stable. The model is more reliable with consistent shapes:

from typing import TypedDict, Literal, Optional, Any

class ToolResult(TypedDict):
    status: Literal['ok', 'not_found', 'error']
    data: Optional[Any]
    error: Optional[str]

def make_result(status, data=None, error=None) -> ToolResult:
    return {'status': status, 'data': data, 'error': error}

print(make_result('ok', data={'temp': 72}))
print(make_result('not_found', error='city not found'))

Include Metadata Hints

Help the model interpret results by including hints in the content:

content = json.dumps({
    'data': rows,
    'note': 'Returned 50 rows (most recent first). There may be more matches.'
})

Binary Data

Don't base64 large blobs into tool messages. Instead, save to storage and return a URL or ID:

result = {
    'image_path': '/tmp/chart-abc.png',
    'thumbnail_url': 'https://...',
    'caption': 'Sales by quarter, 2024'
}
for k, v in result.items():
    print(f"{k}: {v}")

Loop the Model Again

After appending all tool results, call the model again — it will either produce a final answer or call more tools:

class Msg:
    def __init__(self, tool_calls=None, content=None):
        self.tool_calls = tool_calls or []
        self.content = content

class ToolCall:
    def __init__(self, name, args):
        self.name = name
        self.args = args

def call_model(messages, tools):
    if len(messages) < 4:
        return Msg(tool_calls=[ToolCall('get_weather', {'city': 'Paris'})])
    return Msg(content='It is sunny in Paris.')

messages = [{'role': 'user', 'content': 'Weather in Paris?'}]
tools = ['get_weather']
message = call_model(messages, tools)

while message.tool_calls:
    for tc in message.tool_calls:
        result = f'Result of {tc.name}({tc.args})'
        messages.append({'role': 'tool', 'name': tc.name, 'content': result})
        print('Tool call:', tc.name, '->', result)
    message = call_model(messages, tools)

print('Final answer:', message.content)

Auditing Tool Outputs

Log every (tool_call_id, args, result) for debugging. When an agent does something weird, the tool-result log is the first place to look.

Tool Result Format

What does the tool_call_id in a tool message refer to?

Recap

You now own the full tool-call round-trip. Next course: memory — the third pillar of agents.

Frequently asked questions

Is the “Returning Results to the Model” lesson free?

Yes — the full text of “Returning Results to the Model” is free to read here on the web, and the AI Agents course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Agents course, upgrade to CoddyKit PRO.

What will I learn in “Returning Results to the Model”?

Format tool outputs as tool-role messages so the model can read them and continue the conversation. You practise AI Agents with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start AI Agents?

No prior experience is required. AI Agents on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Returning Results to the Model” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this AI Agents lesson?

Yes. Every AI Agents lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. How Function Calling Works
  2. Defining Tool Schemas (JSON Schema)
  3. Choosing Tools at Runtime
  4. Returning Results to the Model
← Back to AI Agents