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, notdocs. 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
errorfield, 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
readbased on its goal. - Prompts — named prompt templates the server offers; the host can list them and let the user invoke by name.
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:
| Sandbox | Model | Best for |
|---|---|---|
| E2B | Hosted Firecracker microVMs | Sub-second Python, easy REST API |
| Modal | Hosted containers + GPU | Long-running compute, ML inference |
| Daytona | Hosted dev environments | Full git/REPL workflows, AI agents |
| Cloudflare Workers / Sandbox | Edge isolates | Low-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.
Step 1
New chatCopy 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_statusand the order IDORD-4821. No other text.Example answer
{"tool": "get_order_status", "input": {"order_id": "ORD-4821"}}Your answer will be worded differently.
Step 2
Same chatYou 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.
Step 3
New chatStart 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.
Step 4
Same chatThis 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.
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.
Step 1
New chatCopy 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
searchorfind.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.
Step 2
New chatOpen 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_employeewith 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.
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.
Step 1
New chatCopy 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.
Step 2
New chatOpen 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_cityfor 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.
Step 3
New chatOpen 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_cityfor 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.
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.
Step 1
New chatRead 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.
Step 2
Same chatCopy 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.
Watch · 5 videos
Function Calling is All You Need — Full Workshop, with Ilan Bigio of OpenAI AI Engineer
LangGraph Deep Dive: Agents with Parallel Function Calling Deploying AI
Building Agents with Model Context Protocol - Full Workshop with Mahesh Murag of Anthropic AI Engineer
[Full Workshop] How to add secure code interpreting in your AI app: Vasek Mlejnsky AI Engineer
Bridging the gap between your API and LLMs Stripe Developers
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]Yao et al., "ReAct: Synergizing Reasoning and Acting in Language Models" (ICLR 2023)
- [2]Wei et al., "Plan-and-Execute Agents" / "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models" — NeurIPS 2022
- [3]Shinn et al., "Reflexion: Language Agents with Verbal Reinforcement Learning" — NeurIPS 2023
- [4]Xu et al., "ReWOO: Decoupling Reasoning from Observations for Efficient Augmented Language Models"
- [5]Anthropic Engineering blog — "How we built our multi-agent research system" (2025)
- [6]LangGraph — official documentation (LangChain)
- [7]Temporal — "Durable Execution for LLM Agents"
- [8]Park et al., "Generative Agents: Interactive Simulacra of Human Behavior" — 2023
- [9]Anthropic — "Introducing computer use, a new Claude 3.5 Sonnet capability" (Oct 2024)
- [10]Anthropic — Tool use / function calling documentation
- [11]OpenAI — Function calling guide
- [12]Anthropic — Model Context Protocol (MCP) specification
- [13]Kwon et al., "Efficient Memory Management for Large Language Model Serving with PagedAttention" — vLLM paper, SOSP 2023
- [14]Zheng et al., "SGLang: Efficient Execution of Structured Language Model Programs" — 2023
- [15]llama.cpp — open-source GGUF-native inference (ggerganov)
- [16]Lin et al., "AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration" — MLSys 2024
- [17]Anthropic — Prompt caching documentation
- [18]Zheng et al., "Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena" — NeurIPS 2023
- [19]Es et al., "Ragas: Automated Evaluation of Information Retrieval Augmented Language Models" — 2023
- [20]Yue et al., "Large Language Model Cascades with Mixture of Thought Representations" — 2024
- [21]GPTCache — open-source semantic cache
- [22]Guo et al., "DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via RL" — 2025
- [23]Jiang et al., "LLMLingua: Compressing Prompts for Accelerated Inference of Large Language Models" — EMNLP 2023
- [24]LiteLLM — unified interface for 100+ LLMs
- [25]OWASP — "Top 10 for LLM Applications" (LLM01 Prompt Injection, 2025)
- [26]Bai et al., "Constitutional AI: Harmlessness from AI Feedback" — Anthropic, 2022
- [27]NVIDIA NeMo Guardrails — open-source toolkit
- [28]Qwen2-VL Team, "Qwen2-VL: Enhancing Vision-Language Model's Perception of the World at Any Resolution" — 2024
- [29]OpenAI — Realtime API documentation
- [30]OpenAI — Production best practices guide