Skip to content

Part 06

Tool Use and Integrations

How an LLM becomes an actor: tool/function schema design, parallel tool calling, Model Context Protocol (MCP) servers/clients/resources/prompts, sandboxed code execution (E2B, Modal, Daytona, Cloudflare), API wrappers, and tool-result formatting for LLM consumption. Each section ships in two voices: the engineer's version (technical, with code & diagrams) and a layman's version (plain English with analogies). প্রতিটি টপিকের শেষে বাংলা ব্যাখ্যাও আছে।

1 section · 30 sources · three voices

01

Tool use & integrations (incl. MCP)

An LLM is just a text generator until you give it tools: a way to call your API, run code, query a database, or read a file. Tool design is the difference between a chatbot demo and a production system. The single highest-leverage decision is the quality of your tool descriptions.

Tool/function schema design

A tool is a JSON Schema (or a Pydantic / Zod object) plus a short description that the LLM reads before deciding to call it. Anthropic and OpenAI both document the same rules:[10][11]

  • Name: verb_noun. search_documents, not docs. Names appear in the model's context window — they're a contract.
  • Description: one sentence on what it does, one on when to use it, and one on what it returns. Treat it like a function docstring the model must read.
  • Parameters: explicit types, enums for closed sets, descriptions for every non-obvious field. Avoid any; the model hallucinates less when the schema is tight.
  • Returns: document the shape. If the tool can fail, return an error field, not a 500.
# Tool schema (Anthropic style)
tools=[{
  "name": "search_documents",
  "description": "Search the company wiki for documents matching a query. Use when the user asks about internal policy, prior projects, or people. Returns top-5 chunks with source URLs and a relevance field 0–1.",
  "input_schema": {
    "type": "object",
    "properties": {
      "query": {"type": "string", "description": "Natural-language query; 3–8 words works best."},
      "filter": {"type": "string", "enum": ["all","policy","engineering","people"], "description": "Optional filter."}
    },
    "required": ["query"]
  }
}]

Number of tools: more than ~20 tools in a single prompt measurably degrades selection accuracy (the many-tools problem). Split into sub-agents by domain, or use a router.

Parallel tool calling

When the model needs to gather information that doesn't depend on itself (e.g. "look up weather in Tokyo and the exchange rate"), it should issue those calls in one turn, not three. Modern APIs return all parallel results at once; the orchestrator runs them concurrently. This is the single biggest latency win in tool-heavy agents.

Model Context Protocol (MCP)

MCP is an open standard (introduced by Anthropic in late 2024, now adopted by OpenAI, Google, and the major IDE vendors) for connecting models to data and tools.[12] The model is the client; the data/tool provider runs an MCP server. The server exposes three primitives:

  • Tools — functions the model can call (the action surface).
  • Resources — read-only data the client can fetch on demand (files, DB rows, web pages). Model decides to read based on its goal.
  • Prompts — named prompt templates the server offers; the host can list them and let the user invoke by name.
MCP Host (Claude Code, Cursor, VS Code, your app) connects to many servers MCP Client JSON-RPC Filesystem server tools: read_file, write_file resources: file://... stdio / sse / http GitHub server tools: create_issue, list_prs resources: repo://... oauth / token Postgres server tools: run_query (read-only) resources: table://... read replica Browser server tools: navigate, click, type resources: screenshot:// isolated profile
MCP architecture: one host can speak to many servers in parallel, each over stdio, SSE, or streamable HTTP. Servers expose tools (actions), resources (data), and prompts (templates).
MCP আর্কিটেকচার: একটি host একাধিক server-এর সাথে কথা বলে (stdio / SSE / HTTP); প্রতিটি server tools (কর্ম), resources (তথ্য) ও prompts (টেমপ্লেট) প্রকাশ করে।

Why MCP matters: before MCP, every IDE / agent app wrote custom integrations for every data source. Now you write one MCP server (e.g. for Postgres) and every MCP-compatible client — Claude Code, Cursor, VS Code, custom agents — can use it.

Sandboxed code execution

Many agent tasks are easiest to express as code ("compute the average of column X"). Letting the model generate and execute code in a sandbox avoids tool explosion and gives you correctness on arithmetic. The four production options in 2025:

SandboxModelBest for
E2BHosted Firecracker microVMsSub-second Python, easy REST API
ModalHosted containers + GPULong-running compute, ML inference
DaytonaHosted dev environmentsFull git/REPL workflows, AI agents
Cloudflare Workers / SandboxEdge isolatesLow-latency, cold-start-fast JS/Wasm

API wrappers as tools

Every internal API becomes a tool: wrap each endpoint with a function that (a) describes its purpose in one sentence, (b) accepts a typed input, (c) returns either the result or an {error, retryable} envelope. The model will route to the right tool if the wrapper is honest about its limits (e.g. "max 100 results, paginate with cursor").

Tool result formatting for LLM consumption

The model re-reads your tool's output as part of its next turn. That output is prompt content. Three rules:[10]

  • Trim ruthlessly. A 10,000-row SQL result will blow your context window. Return the top N, summarise the rest.
  • Format for reading, not for storage. Markdown tables beat JSON arrays for human-shaped reasoning.
  • Include a "what this means" sentence when the result is non-obvious — saves the model a re-derivation.

Practice · 4 tasks

Open any free AI chat: ChatGPT · Claude · Gemini

How practice works
  • A new chat is a fresh conversation with no history. In ChatGPT, Claude, or Gemini, click New chat. It is usually at the top left.
  • Same chat means: keep typing in the chat that is already open. The AI remembers what you sent before.
  • To use a prompt: click Copy, click in the message box of the chat, paste it (Ctrl+V, or press and hold on a phone), and press Enter.
  • AI answers are a little different every time. Your answer does not need to match the example word for word. Look for the same idea.
  • Use made-up data only. Do not paste private information into a chat.

Task 1

Play the tool yourself in a chat

Why this matters

When you build a support chatbot that checks orders, the model cannot look in your database. Your code must run the tool and hand the result back. You need to know what the model sends and what it needs back.

  1. Step 1
    New chat

    Copy this prompt, paste it, and press Enter. Read the reply.

    Prompt
    You are the support assistant for an online shop. You can use ONE tool.
    
    Tool:
    {"name": "get_order_status", "description": "Look up the status of one customer order. Use when the user asks where their order is. Returns status, carrier, and expected delivery date, or an error field if the order is not found.", "input_schema": {"type": "object", "properties": {"order_id": {"type": "string", "description": "Order ID such as ORD-4821"}}, "required": ["order_id"]}}
    
    Rules:
    1. If you need the tool, reply with ONLY a JSON object like {"tool": "name", "input": {...}}. Write no other text.
    2. After I send the tool result, answer the customer in two short sentences.
    
    Customer message: "Hi, my order ORD-4821 has not arrived yet. Where is it?"

    You should see: Only a small JSON object with the tool name get_order_status and the order ID ORD-4821. No other text.

    Example answer
    {"tool": "get_order_status", "input": {"order_id": "ORD-4821"}}

    Your answer will be worded differently.

  2. Step 2
    Same chat

    You are the tool now. Copy this fake tool result, paste it, and press Enter.

    Prompt
    TOOL RESULT for get_order_status:
    
    | field | value |
    |---|---|
    | status | delayed |
    | carrier | SwiftCourier |
    | expected_delivery | 2026-03-14 |
    | delay_reason | warehouse backlog |
    
    Now answer the customer.

    You should see: Two short sentences for the customer. They use the carrier, the new date, and the reason from your table.

    Example answer
    I am sorry, your order ORD-4821 is delayed because of a warehouse backlog. SwiftCourier now expects to deliver it on 2026-03-14.

    Your answer will be worded differently.

  3. Step 3
    New chat

    Start over. Copy the same first prompt again, paste it, and press Enter.

    Prompt
    You are the support assistant for an online shop. You can use ONE tool.
    
    Tool:
    {"name": "get_order_status", "description": "Look up the status of one customer order. Use when the user asks where their order is. Returns status, carrier, and expected delivery date, or an error field if the order is not found.", "input_schema": {"type": "object", "properties": {"order_id": {"type": "string", "description": "Order ID such as ORD-4821"}}, "required": ["order_id"]}}
    
    Rules:
    1. If you need the tool, reply with ONLY a JSON object like {"tool": "name", "input": {...}}. Write no other text.
    2. After I send the tool result, answer the customer in two short sentences.
    
    Customer message: "Hi, my order ORD-4821 has not arrived yet. Where is it?"

    You should see: The same kind of JSON tool request as in step 1.

    Example answer
    {"tool": "get_order_status", "input": {"order_id": "ORD-4821"}}

    Your answer will be worded differently.

  4. Step 4
    Same chat

    This time the tool fails. Copy this error result, paste it, and press Enter. Check that the reply has no made-up date.

    Prompt
    TOOL RESULT for get_order_status:
    
    {"error": "order_not_found", "retryable": false}
    
    Now answer the customer.

    You should see: A good reply says the order was not found and offers help. It does not invent a delivery date. Some models may still guess, so read with care.

    Example answer
    I am sorry, I could not find an order with the ID ORD-4821. Please check the ID and try again, or I can connect you with our support team.

    Your answer will be worded differently.

What just happened

The model cannot run a tool. It only writes text. First it wrote a tool call (a request that says which tool to run and with what input). You ran the tool and pasted the result, so the result became part of the prompt. The model read it and answered. A clear error result told the model not to guess.

You are done when You have two final answers: one with the carrier and date from your table, and one that says the order was not found.

Check yourselfIn this task, who ran the tool? What did the model do with the result?Show answer

You ran the tool, because the model only writes text. The result became part of the prompt, and the model read it to write its answer. This is why a tool must return a clear shape, and an error field when it fails.

Try a harder versionAdd 15 extra made-up rows to the table in step 2. Is the answer still good? Then cut the table back to 4 rows. Which one is easier for the model to read?

Task 2

Compare vague and clear tool descriptions

Why this matters

When you give an AI agent several tools, it picks one by reading each name and description. With vague text it picks the wrong tool or freezes, and your bot gives bad answers.

  1. Step 1
    New chat

    Copy this prompt. It has two tools with vague descriptions. Paste it, press Enter, and write down what the model does.

    Prompt
    You can use these tools:
    [
      {"name": "search", "description": "Searches.", "input_schema": {"type": "object", "properties": {"q": {"type": "string"}}}},
      {"name": "find", "description": "Finds things.", "input_schema": {"type": "object", "properties": {"q": {"type": "string"}}}}
    ]
    
    Rules: If a tool can help, reply with ONLY a JSON object like {"tool": "name", "input": {...}}. If you are not sure which tool is right, reply with one sentence that says why you are not sure. Do not answer the question yourself.
    
    User question: "Who does Farhana Akter report to?"

    You should see: Often one sentence that says the model is not sure which tool to use. Some models just guess search or find.

    Example answer
    I am not sure which tool is right, because both tools only say "searches" or "finds things" and neither says it can look up people.

    Your answer will be worded differently.

  2. Step 2
    New chat

    Open a new chat. Copy this prompt. It has the same question but two clear tools. Paste it and press Enter. Compare with step 1.

    Prompt
    You can use these tools:
    [
      {"name": "search_documents", "description": "Search the company wiki for policy pages and project documents. Use when the user asks about internal policy or past projects. Does NOT return data about people. Returns the top 5 text chunks with source URLs.", "input_schema": {"type": "object", "properties": {"query": {"type": "string", "description": "Natural-language query, 3 to 8 words."}}, "required": ["query"]}},
      {"name": "get_employee", "description": "Look up one employee by full name. Use when the user asks who someone is, who their manager is, or which team they are in. Returns name, job title, manager, and team.", "input_schema": {"type": "object", "properties": {"full_name": {"type": "string", "description": "Full name, for example Farhana Akter."}}, "required": ["full_name"]}}
    ]
    
    Rules: If a tool can help, reply with ONLY a JSON object like {"tool": "name", "input": {...}}. If you are not sure which tool is right, reply with one sentence that says why you are not sure. Do not answer the question yourself.
    
    User question: "Who does Farhana Akter report to?"

    You should see: Most models send one JSON request for get_employee with the full name Farhana Akter.

    Example answer
    {"tool": "get_employee", "input": {"full_name": "Farhana Akter"}}

    Your answer will be worded differently.

What just happened

The question was the same in both prompts. Only the tool text changed. The model reads each tool name and description before it chooses, so this text works like a short manual. A good one has a name with a verb and a noun (get_employee), a sentence on what the tool does and when to use it, and a described input with an example.

You are done when You have two replies: one unsure or guessing, and one clear get_employee request.

Check yourselfWhich three parts of the tool text made the second prompt easier for the model?Show answer

A name with a verb and a noun, such as get_employee. A description that says what the tool does and when to use it. An input field with a description and an example. The model reads all of this before it decides.

Try a harder versionIn the second prompt, change both descriptions to just "Looks things up." Keep the clear names. Does the model still choose well? Which matters more, the name or the description?

Task 3

Spot which tool calls can run together

Why this matters

When an agent needs several facts, waiting for one tool at a time makes the user wait. In a travel or support bot, running independent calls together makes the answer much faster.

  1. Step 1
    New chat

    Copy this prompt, paste it, and press Enter. Count the tool calls in the list.

    Prompt
    You can use these tools:
    1. get_weather(city): gets the current weather for one city.
    2. get_exchange_rate(from, to): gets the exchange rate between two currency codes, for example USD and BDT.
    3. get_user_city(user_id): gets the home city of a user.
    
    Rules: Reply with ONLY a JSON list of tool calls, for example [{"tool": "name", "input": {...}}]. Put in the list every call you can make right now. If a call needs the result of another call, leave it out. Write no other text.
    
    User question: "What is the weather in Tokyo, and how many BDT is 1 USD?"

    You should see: 2 calls in one list: one weather call for Tokyo, one exchange-rate call from USD to BDT.

    Example answer
    [{"tool": "get_weather", "input": {"city": "Tokyo"}}, {"tool": "get_exchange_rate", "input": {"from": "USD", "to": "BDT"}}]

    Your answer will be worded differently.

  2. Step 2
    New chat

    Open a new chat. Copy this prompt, paste it, and press Enter. Count the calls. Ask yourself why the list is short.

    Prompt
    You can use these tools:
    1. get_weather(city): gets the current weather for one city.
    2. get_exchange_rate(from, to): gets the exchange rate between two currency codes, for example USD and BDT.
    3. get_user_city(user_id): gets the home city of a user.
    
    Rules: Reply with ONLY a JSON list of tool calls, for example [{"tool": "name", "input": {...}}]. Put in the list every call you can make right now. If a call needs the result of another call, leave it out. Write no other text.
    
    User question: "What is the weather in the city where user U-77 lives?"

    You should see: Only 1 call: get_user_city for U-77. The weather call needs the city first.

    Example answer
    [{"tool": "get_user_city", "input": {"user_id": "U-77"}}]

    Your answer will be worded differently.

  3. Step 3
    New chat

    Open a new chat. Copy this prompt, paste it, and press Enter. Write down which call is in the list and which call is missing.

    Prompt
    You can use these tools:
    1. get_weather(city): gets the current weather for one city.
    2. get_exchange_rate(from, to): gets the exchange rate between two currency codes, for example USD and BDT.
    3. get_user_city(user_id): gets the home city of a user.
    
    Rules: Reply with ONLY a JSON list of tool calls, for example [{"tool": "name", "input": {...}}]. Put in the list every call you can make right now. If a call needs the result of another call, leave it out. Write no other text.
    
    User question: "Compare the weather in Tokyo with the weather in the city where user U-77 lives."

    You should see: 2 calls: weather for Tokyo and get_user_city for U-77. The weather call for U-77's city is missing, because it must wait.

    Example answer
    [{"tool": "get_weather", "input": {"city": "Tokyo"}}, {"tool": "get_user_city", "input": {"user_id": "U-77"}}]

    Your answer will be worded differently.

What just happened

The weather in Tokyo and the BDT rate do not need each other. The model asks for both in one turn, and they run at the same time. These are parallel tool calls. The weather for U-77's city needs the city first, so it must wait for the next turn. With parallel calls, the total wait is the slowest call, not the sum of all calls.

You are done when You have 3 lists with 2 calls, 1 call, and 2 calls, and you know which call was left out in the last one.

Check yourselfWhy do parallel tool calls make an agent faster? When can you not use them?Show answer

Independent calls run at the same time, so the wait is only as long as the slowest call. If one call needs the result of another call, it must wait for the next turn.

Try a harder versionWrite a question that needs 3 calls: two that can run together and one that must wait. Test it in a new chat. Does the model split the calls correctly?

Task 4

Sort an MCP server's features

Why this matters

When your team has many apps and many data sources, building every link by hand takes weeks. MCP is a shared standard that cuts this work. You also need to know its three kinds of features.

  1. Step 1
    New chat

    Read the 8 features in this prompt. On paper, guess tool, resource, or prompt for each. Then copy it, paste it, and press Enter. Compare.

    Prompt
    An MCP server for a Postgres database offers these features:
    1. run_query: runs a SQL query and returns the rows
    2. The list of all tables and columns, readable at the address db://schema
    3. A saved template called "weekly-sales-report" that the user picks by name from a menu
    4. insert_row: adds a new row to a table
    5. A read-only CSV file of yesterday's orders, at the address db://exports/orders-yesterday
    6. A template called "explain-this-slow-query" that fills in a query the user gives
    7. delete_old_logs: deletes log rows older than 90 days
    8. The text of one customer record, at the address db://customers/1042
    
    MCP has three primitives:
    - Tool: a function the model can call to do an action.
    - Resource: read-only data the client can fetch on demand.
    - Prompt: a named prompt template the user can pick.
    
    Sort each feature into one primitive. Reply with a table: number, primitive, and a reason in 10 words or fewer.

    You should see: A table. Features 1, 4, 7 are tools (actions). Features 2, 5, 8 are resources (read-only data at an address). Features 3, 6 are prompts (templates).

    Example answer
    1 | Tool | Runs a query, an action
    2 | Resource | Read-only schema at an address
    3 | Prompt | Named template the user picks
    4 | Tool | Adds a row, changes data
    5 | Resource | Read-only file at an address
    6 | Prompt | Template the user fills in
    7 | Tool | Deletes rows, an action
    8 | Resource | Read-only record at an address

    Your answer will be worded differently.

  2. Step 2
    Same chat

    Copy this prompt, paste it in the same chat, and press Enter. Check the numbers with a calculator.

    Prompt
    We have 3 apps (an IDE, a chat app, and a custom agent) and 4 data sources (Postgres, a wiki, GitHub, and a file store). How many custom integrations do we write without MCP? How many pieces do we write with MCP (one client per app, one server per source)? Show the formula and explain in 2 sentences why the numbers differ.

    You should see: Without MCP: 3 × 4 = 12 integrations. With MCP: 3 + 4 = 7 pieces.

    Example answer
    Without MCP: 3 apps × 4 sources = 12 custom integrations.
    With MCP: 3 clients + 4 servers = 7 pieces.
    The numbers differ because without MCP every app needs its own link to every source. With MCP each app and each source only has to speak the one shared standard.

    Your answer will be worded differently.

What just happened

MCP (Model Context Protocol) is an open standard that connects AI apps to data and tools. A server offers three kinds of features: tools (the model does an action), resources (read-only data it can fetch), and prompts (named templates the user picks). Anything that changes data is a tool. Without MCP you build apps × sources links. With MCP you build apps + sources pieces.

You are done when You have a table that sorts all 8 features, and you saw 12 compared with 7.

Check yourselfWhy is delete_old_logs a tool and not a resource?Show answer

A resource is read-only data that the client fetches. Deleting rows is an action, and actions are tools.

Try a harder versionAdd a 9th feature of your own that is hard to sort, for example a read-only data feed that also needs an input. Ask the model, then argue with its answer.

Watch · 5 videos

References

Sources

All citations resolve to primary papers (arXiv), vendor docs (OpenAI, Anthropic, Google), or official team blogs. IDs were verified by fetching each page and extracting the citation metadata.

  1. [1]Yao et al., "ReAct: Synergizing Reasoning and Acting in Language Models" (ICLR 2023)
  2. [2]Wei et al., "Plan-and-Execute Agents" / "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models" — NeurIPS 2022
  3. [3]Shinn et al., "Reflexion: Language Agents with Verbal Reinforcement Learning" — NeurIPS 2023
  4. [4]Xu et al., "ReWOO: Decoupling Reasoning from Observations for Efficient Augmented Language Models"
  5. [5]Anthropic Engineering blog — "How we built our multi-agent research system" (2025)
  6. [6]LangGraph — official documentation (LangChain)
  7. [7]Temporal — "Durable Execution for LLM Agents"
  8. [8]Park et al., "Generative Agents: Interactive Simulacra of Human Behavior" — 2023
  9. [9]Anthropic — "Introducing computer use, a new Claude 3.5 Sonnet capability" (Oct 2024)
  10. [10]Anthropic — Tool use / function calling documentation
  11. [11]OpenAI — Function calling guide
  12. [12]Anthropic — Model Context Protocol (MCP) specification
  13. [13]Kwon et al., "Efficient Memory Management for Large Language Model Serving with PagedAttention" — vLLM paper, SOSP 2023
  14. [14]Zheng et al., "SGLang: Efficient Execution of Structured Language Model Programs" — 2023
  15. [15]llama.cpp — open-source GGUF-native inference (ggerganov)
  16. [16]Lin et al., "AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration" — MLSys 2024
  17. [17]Anthropic — Prompt caching documentation
  18. [18]Zheng et al., "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena" — NeurIPS 2023
  19. [19]Es et al., "Ragas: Automated Evaluation of Information Retrieval Augmented Language Models" — 2023
  20. [20]Yue et al., "Large Language Model Cascades with Mixture of Thought Representations" — 2024
  21. [21]GPTCache — open-source semantic cache
  22. [22]Guo et al., "DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via RL" — 2025
  23. [23]Jiang et al., "LLMLingua: Compressing Prompts for Accelerated Inference of Large Language Models" — EMNLP 2023
  24. [24]LiteLLM — unified interface for 100+ LLMs
  25. [25]OWASP — "Top 10 for LLM Applications" (LLM01 Prompt Injection, 2025)
  26. [26]Bai et al., "Constitutional AI: Harmlessness from AI Feedback" — Anthropic, 2022
  27. [27]NVIDIA NeMo Guardrails — open-source toolkit
  28. [28]Qwen2-VL Team, "Qwen2-VL: Enhancing Vision-Language Model's Perception of the World at Any Resolution" — 2024
  29. [29]OpenAI — Realtime API documentation
  30. [30]OpenAI — Production best practices guide