
How AI Agents Connect to External Tools
A user types "reschedule my Thursday call with Priya to Monday morning." Between that sentence and a modified calendar event, roughly eleven things have to happen — and only one of them involves the model.
The model has to be told a rescheduling capability exists, in a format it can reason over. It has to pick that capability over a dozen near-neighbours. It has to emit well-formed arguments. Something has to catch that emission, find the right credential for that specific user's Google account, refresh it if it expired overnight, call the API, handle a 429, interpret a partial failure, decide whether a retry would double-book, shrink a 40 KB response into something worth spending context on, hand it back, and leave an audit trail someone can read six months later during a security review.
Ten of those eleven steps are ordinary distributed-systems work. Most writing on this topic spends its time on the one step that isn't, which is why teams keep shipping demos that work and products that don't.
This article covers the whole path. It separates the layers that are usually blurred together, explains what actually changed in MCP this year, and gives you a decision framework for choosing a connection method — with particular attention to the case most guides skip: an agent acting inside your customers' accounts rather than your own.
The five layers of agent-to-tool connectivity
Almost every architectural argument about agent integrations is really a category error — two people discussing different layers as though they were the same one. It helps to name them.
Layer | Question it answers | Typical technology | Who owns it |
|---|---|---|---|
1. Tool contract | What can the agent do, and how does it express intent? | JSON Schema tool definitions, function calling | Your prompt/tool authors |
2. Transport | How does the intent physically reach the tool? | Direct dispatch, MCP, hosted connectors, A2A | Your runtime |
3. Connectivity | Whose credentials, against which tenant, with what scopes? | OAuth 2.1, token vault, key management | Integration layer |
4. Execution | What happens on retries, timeouts, rate limits, partial failure? | Idempotency keys, queues, backoff, pagination | Integration layer |
5. Governance | What was allowed, what happened, who can see it? | Policy engine, approval gates, audit log | Platform/security |
Two observations follow immediately.
First, the model only participates in Layer 1. Everything below it is software you would need even if the caller were a cron job. This is why "we'll add MCP" is rarely a plan — MCP is a Layer 2 decision, and Layer 2 is not usually where the difficulty lives.
Second, the layers fail independently. An agent that picks the wrong tool has a Layer 1 problem, solved by better schemas. An agent that picks the right tool and gets a 401 has a Layer 3 problem. An agent that succeeds twice and creates two invoices has a Layer 4 problem. Teams that treat these as one undifferentiated "the agent is flaky" bucket end up tuning prompts to fix token refresh bugs.

Layer 1 — The tool contract: what the model actually sees
An agent does not "call an API." It emits a structured request that names a tool and supplies arguments, and your code does the calling. The model's entire view of the outside world is a list of tool definitions serialized into its context window — typically a name, a natural-language description, and a JSON Schema for the parameters.
That is the whole interface. The model cannot read your API docs, inspect your database, or ask a colleague what status_id: 4 means. If it isn't in the schema, it doesn't exist.
The loop itself is simple and provider-agnostic:
Tool definitions go into the request alongside the conversation.
The model returns either a normal message or a tool-call block naming a tool and its arguments.
Your runtime executes it and appends the result to the conversation as a tool-result block.
The model reasons over the result and either answers or calls another tool.
Anthropic, OpenAI, and Google differ in field names and streaming semantics but not in this shape. Portability across models is rarely the hard part.
Why the description field is the real API
Tool selection is a retrieval problem dressed as a reasoning problem. When an agent picks send_message instead of create_draft, the usual cause is not model weakness — it's two descriptions that are near-identical in embedding space.
A description written for a human reads: "Creates a task." A description written for a model reads: "Creates a new task in a specific project. Use when the user wants work tracked. Do not use to update an existing task — use update_task with its id. Requires project_id; call list_projects first if you don't have one."
The second version encodes selection boundaries, prerequisites, and negative cases. Those three things do more for reliability than any amount of system-prompt tuning, because they're attached to the decision rather than sitting several thousand tokens away.
The tool-contract checklist
Before a tool goes into production, it should pass all of these. In practice this list catches more agent bugs than anything else on the page.
Verb-first, unambiguous name.
create_invoice, notinvoiceorhandle_billing.Explicit negative guidance. Name the tools this one is most likely to be confused with, and say when not to use it.
Enums instead of free strings.
status: "open" | "closed"removes a whole class of hallucinated values that free-text fields invite.Prerequisites declared. If a call needs an ID the model can't know, say which tool produces it.
Constrained, informative output. Return the fields the agent needs to decide what's next — not the provider's full response object. A 40 KB payload costs context on every subsequent turn of the conversation, not just once.
Errors written for a reader, not a logger.
"No project matches 'Q3 launch'. Call list_projects to see valid names."recovers.{"error":"ENOENT"}loops.Idempotency stated. If calling twice is unsafe, the schema and description should say so, and the runtime should enforce it.
Side effects visible in the name. A tool called
get_customermust not send an email.
A useful design constraint: write each definition as though it will be read once, by a competent contractor, with no ability to ask follow-up questions. That is precisely the situation the model is in.
Layer 2 — Transport: how the call physically travels
Once the model has emitted a tool call, something has to route it. There are four common answers, and they are not interchangeable.
Direct function calling
Your runtime holds a dispatch table mapping tool names to local functions. Lowest latency, fewest moving parts, complete control. It's the correct default for tools that are genuinely yours — internal services, database queries, business logic.
The cost is that every capability is compiled into your application. Adding a tool means a deploy. Sharing tools across teams means publishing a library.
MCP, and what changed in 2026
The Model Context Protocol standardizes the interface between an agent (client) and a tool provider (server), so the same server works with any compliant client. It is JSON-RPC 2.0 over HTTP, now stewarded by the Linux Foundation rather than any single vendor.
Most published material about MCP is now describing a protocol that no longer exists. The 2026-07-28 revision is the largest structural change the spec has had, and it is not backward compatible in several places. If your architecture notes were written before mid-2026, the following are the parts to re-check:
Sessions are gone. The
initialize/initializedhandshake and theMcp-Session-Idheader have been retired. Each request now carries its own protocol version, client identity, and capabilities inside_meta. There's an optionalserver/discoverRPC for clients that want capabilities upfront, but it isn't required. The practical payoff: any request can land on any server instance behind a plain round-robin load balancer, with no shared session store.Method and tool names travel in headers.
Mcp-MethodandMcp-Nameare now required on Streamable HTTP requests, so a gateway, rate limiter, or WAF can route and authorize without parsing JSON bodies. This is a meaningful operational unlock — MCP traffic can be governed with the same infrastructure as the rest of your API surface.Mid-call user input works statelessly. Multi Round-Trip Requests replace the old server-initiated elicitation and sampling calls that required a held-open stream. The server returns
resultType: "input_required"with the questions it needs answered, and the client retries the original call withinputResponsesattached. This is what makes "confirm before this deletes data" possible without persistent connections.Tool catalogs are cacheable.
tools/list,prompts/list,resources/list, andresources/readnow carryttlMsandcacheScope, with deterministic ordering — which also keeps upstream prompt caches stable across reconnects.Auth hardened. Clients must validate the
issparameter per RFC 9207 before redeeming an authorization code, closing an authorization-server mix-up hole. Dynamic Client Registration is formally deprecated in favour of Client ID Metadata Documents. Enterprise Managed Authorization has landed as a formal extension, giving identity providers a standard seat in the delegation chain.Deprecations now come with a runway. Roots, sampling, and logging are deprecated, as is the legacy HTTP+SSE transport, with a stated twelve-month minimum window.
The strategic read: MCP has stopped being an AI-specific protocol with unusual operational requirements and become an ordinary HTTP workload. That is good news for anyone who has to run it in production, and it removes most of the "we can't operate this" objections that stalled MCP adoption in 2025.
What MCP does not do is worth stating plainly. It is a delivery protocol. It does not obtain OAuth tokens for your customers, store them, refresh them, scope them per tenant, retry failed calls, or tell you why a sync broke. Exposing tools over MCP and still needing an integration layer underneath is the normal outcome, not a sign you did it wrong.
Hosted connectors
Model providers increasingly host the transport themselves. OpenAI's Responses API accepts an mcp tool type with either a server_url or a connector_id plus an authorization token, and supports require_approval and allowed_tools for scoping. It is worth understanding the boundary: the platform relays a bearer token you supply on every request — obtaining that token, refreshing it, and storing it per end user remains your application's job.
This pattern is excellent for prototyping and for first-party tools. It gets uncomfortable when you need per-customer credentials, because the credential lifecycle is the part that wasn't outsourced.
A2A solves a different problem
Agent2Agent handles agent-to-agent delegation — one agent discovering another's capabilities via a signed Agent Card and handing off a task. Also a Linux Foundation project, v1.0 since March 2026, with adoption across the major cloud agent platforms.
A2A and MCP are complementary rather than competing: MCP connects an agent to its tools, A2A connects agents to each other. If your question is "how does my agent update a customer's CRM," A2A is not the answer. If it's "how does my agent hand a specialist subtask to a partner's agent," it is.
Transport comparison
Direct dispatch | MCP | Hosted connector | A2A | |
|---|---|---|---|---|
Best for | Your own services | Reusable tool surfaces, third-party clients | Fast integration with one model provider | Cross-vendor agent delegation |
Latency | Lowest | One network hop | Provider-dependent | Highest (agent round-trip) |
Works across model vendors | Yes (you own it) | Yes | No | Yes |
Handles per-user auth | No | No (spec defines the flow, not the storage) | Partially — you still supply tokens | No |
Discoverable by external clients | No | Yes | Within that provider | Yes (Agent Cards) |
Operational cost | Low | Moderate (a service to run) | Low | Moderate |
Layer 3 — Connectivity: the layer that actually costs money
This is where projects slip. Not because the concepts are exotic, but because the surface area is larger than it looks from the outside, and none of it is visible in a demo.
Two identities, one intersection rule
Every agent action involves two distinct identities:
The workload identity — the agent application itself, registered as an OAuth client.
The user identity — the human on whose behalf the action is taken.
The rule that keeps you out of trouble: an agent's effective permissions are the intersection of what the agent is allowed to do and what the user is allowed to do — never the union, and never the agent's rights alone. An agent holding a service account with broad access will happily read records the requesting user could never see, and no amount of prompting reliably prevents it. This is an access-control decision, not a model behaviour decision, and it belongs in code.
Delegated access (Authorization Code + PKCE, scoped to the individual user) is the default for anything touching user data. App-only workload credentials are for genuinely user-independent background work, and should be treated as the exception requiring justification.
Multi-hop delegation — agent calls agent calls tool — is the open edge. RFC 8693 token exchange handles a single hop cleanly; the IETF's identity-chaining work extends it to chains, and Cross App Access has begun landing in vendor products and in MCP's authorization extension. If you're building something that will face an enterprise security review in the next two years, this is the area worth tracking closely, because retrofitting delegation semantics is expensive.
The multi-tenant problem
Here is the fork in the road that most guides never mention.
If your agent connects to your own systems, you need one set of credentials per service. Store them in a secrets manager, rotate them, move on. This is a weekend of work.
If your agent connects to your customers' accounts — updating their HubSpot, reading their Jira, posting to their Slack — you need something categorically different:
An OAuth flow you can present inside your own UI, per provider, per end user
Encrypted, tenant-isolated storage for tokens with wildly different lifetimes and refresh semantics
Proactive refresh, because a token that expires mid-conversation surfaces as an agent failure to the user
Per-tenant rate limit accounting, since providers meter the token, not your app
Provider-specific scope handling, so a customer who granted read-only doesn't produce write attempts
Graceful revocation, because customers revoke access and the agent must degrade rather than error
Per-customer observability, because "it's broken" support tickets are otherwise unanswerable
Multiply by the number of providers you support. Each one has its own OAuth quirks, its own pagination style, its own idea of what a rate limit means, and its own breaking-change cadence. This — not tool calling, not MCP — is what makes agent integrations expensive.
The connect-to-revoke lifecycle
Design the whole arc before you build any of it:
Discover — the user sees which integrations exist and what each will access
Connect — OAuth consent, ideally without leaving your product
Scope — which specific actions this connection permits, stored explicitly
Operate — token refresh, rate limiting, error surfacing, all invisible when working
Observe — per-user logs the customer's own admin can inspect
Revoke — from either side, with the agent's tool list updating accordingly

Step 6 is the one that gets skipped and the one that shows up in security questionnaires. An agent whose tool list doesn't shrink when a customer disconnects an app is offering capabilities it can no longer deliver.
Layer 4 — Execution semantics
Agents retry. They retry after timeouts, after ambiguous errors, and sometimes after successes they failed to parse. Any tool with side effects needs to survive that.
Idempotency. Every mutating tool call should carry an idempotency key derived from the intent, not from the attempt. Stripe's model is the reference implementation and worth copying wholesale. Without it, a network blip becomes a duplicate charge.
Retry policy belongs below the model. Exponential backoff with jitter, in your integration layer, invisible to the agent. Letting the model decide whether to retry burns tokens and produces inconsistent behaviour across runs.
Pagination has to be bounded. An agent asked to "check all open tickets" against a 12,000-ticket queue will page until something breaks. Cap results, return an explicit has_more with a continuation token, and let the tool description say what the cap is.
Rate limits are a tenant-level concern. Providers meter per token. Ten customers on one connector means ten independent budgets, and one heavy user must not be able to exhaust another's.
Long-running work needs a different shape. Anything past a few seconds shouldn't block a tool call. MCP's Tasks extension formalizes this with a poll-based tasks/get — but the underlying pattern is older than MCP and applies regardless of transport: return a handle immediately, let the agent poll or receive a callback.
Partial failure needs a vocabulary. "Created the ticket, failed to attach the file" is a real and common outcome. If your tool returns a boolean, the agent will guess, and it will guess wrong in both directions.
Layer 5 — Governance and blast radius
The security model for tool-using agents is not primarily about the model. It's about what combination of capabilities you granted in a single execution path.
The sharpest available framing is Simon Willison's lethal trifecta: an agent becomes an exfiltration tool when it simultaneously has (1) access to private data, (2) exposure to untrusted content, and (3) a channel to send data outward. Each is individually reasonable. Together they mean an attacker who can plant instructions anywhere the agent reads — a support ticket, a web page, an email, a third-party API response — can direct it to fetch private data and ship it out. The model has no reliable way to distinguish instructions in data from instructions in its system prompt, and the 2026 incident record across multiple major AI productivity products bears this out.

Filtering untrusted content doesn't work reliably. Telling the model to ignore embedded instructions doesn't work reliably. What works is topology:
Break the triangle per execution path. An agent that reads untrusted content should not, in the same run, hold credentials to private systems and have an outbound channel.
Split agents by trust level rather than giving one agent everything.
Human approval gates on irreversible actions — sends, deletes, payments, external posts. MCP's MRTR makes this expressible in-protocol; it can equally be a wrapper in your own runtime.
Enumerate outbound channels honestly. Image URLs, link previews, webhook calls, and error reporting are all exfiltration paths. So is any tool that accepts a URL.
Log the call, not the conversation. Tool name, arguments, acting user, tenant, result status, timestamp. This is what an auditor asks for and what your own debugging depends on.
The tool-count problem nobody plans for
Every tool definition occupies context on every single request. Twenty tools is unremarkable. Two hundred — entirely normal once you're exposing several connectors per customer — is a real cost in tokens, latency, and selection accuracy, because near-identical tools crowd each other.
Three mitigations are now first-class, and they compose:
Deferred loading with tool search. Rather than sending every definition upfront, mark tools with defer_loading and let the model retrieve relevant ones on demand. Anthropic exposes this via a tool search beta; the trade-off is that search quality becomes the new bottleneck, and tool names and descriptions have to be written to be findable, not just understandable.

Programmatic tool calling. Instead of one model round-trip per tool call, the model writes code that orchestrates several calls in a sandbox, and only the final result enters context. Anthropic's documentation reports that on agentic search benchmarks — BrowseComp and DeepSearchQA — adding programmatic tool calling on top of basic search tools improved performance by roughly 11% on average while using about 24% fewer input tokens. The canonical example is checking budget compliance across twenty employees: twenty round-trips and thousands of line items collapse into one script returning a handful of rows.
Context editing and caching. Old tool results can be cleared once they've served their purpose; stable tool definitions can be prompt-cached so you pay for them once. Neither reduces what you send — they reduce what you pay and what you carry.
The design implication: a large catalog is fine, an undifferentiated large catalog is not. Group tools by connector, name them consistently, and make sure the description of hubspot_create_contact says something salesforce_create_contact doesn't.
Choosing a connection method
Work down this table until a row matches. The first match is usually right.
If this is true | Use | Because |
|---|---|---|
The tool is your own service, called only by your own agent | Direct function dispatch | No protocol tax, no extra hop, full control |
You want external agents (Claude, ChatGPT, Cursor, a customer's own agent) to act inside your product | Expose an MCP server | Standard discovery; one surface serves every compliant client |
Your agent needs one or two third-party APIs, with credentials you control | Direct API calls behind your own tools | A connector platform is overhead at this scale |
Your agent needs your customers' third-party accounts, across several providers | Integration infrastructure with per-end-user auth | Token lifecycle across tenants is the actual work; it doesn't get cheaper as you add providers |
You need normalized reads across many providers in one category (all CRMs, all ATSs) | Unified API | One schema beats N schemas — accepting that it flattens provider specifics |
You need customer-configurable multi-step logic, not single actions | Embedded iPaaS / workflow layer | Agents are bad at orchestrating long deterministic sequences; give them one tool that runs the sequence |
Another team's or vendor's agent should own a subtask | A2A | Agent-to-agent delegation with capability discovery |
Two clarifications this table depends on, since the terms get used interchangeably in vendor content and shouldn't be:
A unified API normalizes many providers behind one schema. Excellent for reads, lossy at the edges, historically weaker on writes.
An embedded iPaaS lets your customers configure integrations inside your product. It solves configuration and workflow, and adds latency when an agent just needs a single action.
Integration infrastructure is the auth, execution, and observability layer underneath both. It's what you're building yourself if you're not buying it, whatever else you buy.
An agent product frequently needs two of these at once: low-latency single actions for the agent, plus a workflow surface for the deterministic sequences you don't want a model improvising.
The build-vs-buy arithmetic
Don't take anyone's number for this, including ours. Take the model and use your own inputs.

One-time cost per connector
Build_initial = OAuth flow + token storage/refresh
+ endpoint mapping for the actions you need
+ pagination + rate limit handling
+ error normalization
+ sandbox account setup and testingMost teams land somewhere between one and three engineer-weeks for a well-documented provider with standard OAuth, and considerably more for the ones that aren't — the providers with non-standard auth, undocumented limits, or per-customer API versions.
Recurring cost per connector per year
Build_ongoing = breaking API changes
+ auth/scope model changes
+ new endpoints customers ask for
+ support burden (per-customer failures)
+ on-call for silent sync breakageThe recurring line is the one that gets underestimated, because it doesn't appear in the first quarter. It's also the line that scales with customers as well as connectors: 30 connectors across 500 customers is 15,000 live credential relationships, each capable of breaking independently.
The comparison to run
Total_build = Σ(Build_initial) + (years × Σ(Build_ongoing))
Total_buy = platform fee + integration work on top
+ cost of gaps the platform doesn't cover
Break-even = the connector count where Total_buy < Total_buildThree honest observations about the result:
At one to three connectors, building usually wins. The platform overhead isn't worth it, and you keep full control.
The curve is not linear. Build cost grows with connectors and customers; platform cost grows mostly with usage. The lines cross earlier than most teams project, typically once the recurring maintenance of the fifth or sixth connector overlaps with building the tenth.
The variable that decides it is rarely cost. It's whether integrations are your product's differentiation. If customers choose you because of your Salesforce depth, own it. If integrations are table stakes that gate deals, every week spent on OAuth refresh logic is a week not spent on the thing they actually buy.
Six failure modes and what causes them
The agent calls the wrong tool. Layer 1. Two descriptions that don't distinguish themselves. Fix the schemas before touching the system prompt.
It works for you and fails for customers. Layer 3. You tested with one credential and shipped a multi-tenant assumption you never validated. Test with at least three tenants at different scope levels.
Duplicate records appear intermittently. Layer 4. A retry after an ambiguous timeout, with no idempotency key.
Quality degrades as you add connectors. Layer 1 crowding plus Layer 4 context bloat. Introduce deferred loading before the catalog gets large, not after.
The agent claims success when nothing happened. Layer 4. A tool that returns 200 for a partial failure, or an error message the model reads as a status update.
It passed the demo and failed the security review. Layer 5. No per-user audit trail, no approval gate on irreversible actions, and an execution path holding all three legs of the trifecta.
Where integration infrastructure fits
Nothing in Layers 3 through 5 is intellectually difficult. It's just relentless — a long tail of provider-specific behaviour that has to be maintained indefinitely by people who could be building your product instead.
This is the gap integration infrastructure exists to close. viaSocket is built for the customer-facing case specifically: SaaS and AI companies that need their agents acting inside their users' third-party accounts, with per-end-user OAuth, managed token lifecycle, and a connector catalog they don't maintain — either embedded into their own product UI, or exposed to their customers as a managed MCP endpoint so external agents like Claude or ChatGPT can act inside their app.
The evaluation question isn't which vendor has the longest connector list. It's narrower and more useful: which layers am I outsourcing, which am I keeping, and does the platform's model of "a user" match mine? A platform designed for internal automation and one designed for multi-tenant customer-facing integrations look similar in a demo and diverge sharply the moment you have five hundred customers with independently revocable credentials.
Frequently asked questions
Is MCP a replacement for APIs?
No. MCP is a description and invocation layer that sits in front of APIs. The underlying REST or GraphQL endpoint still does the work; MCP standardizes how an agent discovers what's available and calls it. You can't skip the API by adopting MCP.
MCP or function calling — which should I use?
They're different layers, so the question doesn't quite parse. Function calling is the model-side capability of emitting a structured tool call; every major model has it. MCP is a transport for delivering tools to any compliant client. You use function calling always, and MCP when you want tools reachable by clients you don't control.
How do AI agents authenticate to third-party apps?
Almost always OAuth 2.1 Authorization Code with PKCE, scoped to an individual user, with the resulting access and refresh tokens stored per user per tenant. The agent should act with the intersection of its own permissions and that user's — never with a broad service account that bypasses the user's own access controls.
How many tools can an agent handle before quality drops?
There's no universal threshold; it depends far more on how distinguishable your tools are than on the raw count. Practical guidance: below about twenty well-differentiated tools, load everything. Above that, watch for selection errors between similar tools and adopt deferred loading with tool search before the catalog becomes unwieldy.
Do I need MCP if my agent only calls my own APIs?
Probably not. Direct dispatch is faster and simpler. MCP earns its place when you want other people's agents calling your tools, or your agent calling tools you didn't build.
What broke in the 2026-07-28 MCP revision?
The protocol became stateless. The initialize handshake and Mcp-Session-Id header were removed, server-initiated requests were replaced by Multi Round-Trip Requests, and Mcp-Method/Mcp-Name headers became required. Roots, sampling, logging, and the legacy HTTP+SSE transport are deprecated with a twelve-month minimum window. Servers on the new revision may not interoperate with older clients.
Can an agent handle long-running operations?
Yes, but not inside a blocking tool call. Return a handle immediately and let the agent poll or receive a callback. MCP formalizes this as the Tasks extension; the pattern works on any transport.
What's the single biggest security risk?
Indirect prompt injection reaching an execution path that also holds private data access and an outbound channel. The mitigation is architectural — separate those capabilities across execution paths — not a prompt instruction telling the model to be careful.
Read More

