Tools that come and go: handing agents the map
In my last post I dropped a little side note: "I might experiment with exposing skills for WebMCP 🤔".
Because the more I play with WebMCP tools, the more I keep running into the same gap:
A website knows its whole journey. A visiting agent only sees the tools registered right now. So how does it learn the rest?
Today I want to walk through that problem, a few ideas I've been testing against it, and a freshly announced discovery proposal that might hand us a useful piece of the answer 👇.
To make this less abstract, I've built Forge Titan - a small experiment where an agent assembles a robot using WebMCP tools. The whole demo is on GitHub: Kulikowski/webmcp-ard-exploration - so you can run every condition yourself. I'll use it as the running example and reveal the journey as we go 🤖.

Tools that are always there, tools that come and go
WebMCP tools are registered imperatively from page JavaScript - document.modelContext.registerTool({...}) - and unregistered by aborting a signal you passed at registration time. That tiny API surface hides a real architectural choice:
1️⃣ Static tools. You register the same toolset on every page load, no matter where the user navigates or what state the assembly is in. list_parts, mount_torso, deploy_titan - always there, like a global API the page happens to host. Simple to build, easy for the agent to enumerate.
2️⃣ Dynamic tools. You register and unregister tools as the app moves - by route, or by application state. In Forge Titan, reserve_part appears after inventory inspection and deploy_titan only after the tests pass. The toolset reflects the UI state for agents.
Forge Titan makes the difference easy to see. Its assembly journey crosses six stations and more than twenty tools. In static mode the agent sees everything from list_parts to deploy_titan before the torso is even mounted. Dynamic mode opens the journey with just list_parts and check_stock; after the parts are inspected, reserve_part appears. Complete inventory and that surface is replaced by the structural assembly tools.
To be clear, this is not an either/or choice - it's per tool, not per site. In practice you'd probably mix the two: a small stable core that makes sense everywhere, with state-gated tools appearing and disappearing on top of it as the journey unfolds. Forge Titan does exactly that: a handful of workshop tools stay registered in every state, and the assembly tools come and go with the build.
Dynamic feels right, doesn't it? The tool list stays small, and each tool is intended to be useful in the current state. It mirrors how I think about building UIs - I don't expect a deploy button before the robot passes testing 🤷♂️.
There is an important engineering detail here: registration is not enforcement. State can change between discovery and invocation, so every tool still needs to validate permissions and preconditions when it runs. Hiding a tool keeps the surface relevant; it is not an authorization boundary.
But there is a catch - with dynamic tools, the agent's visibility into tools shrinks to whatever is registered right now.
Planning without a map
Agents that work step by step usually run some flavor of the ReAct pattern (from the paper that named it): reason about the goal, act by calling a tool, observe the result, repeat. Each loop the agent picks its next best action from whatever tools it can currently see.
With static tools, the agent can at least attempt a plan upfront - all the puzzle pieces are on the table from step one.
With dynamic tools, it cannot see the full journey from the tool list alone. The tools for step five may not appear until steps one through four are done. Imagine a car navigation that only ever shows you the next turn - never the whole route 😅. The agent can still learn from the page, previous knowledge or tool results, but the current tool list gives it less information to plan with.
For a two-step flow? The agent will probably figure the route out as it goes. But for a really long journey - configure, validate, order, assemble, test - it starts to matter a lot. An agent with the full route can start with a plan. An agent without it discovers the route turn by turn, which I suspect means more model calls and more detours. That's exactly what I ended up testing - the results are near the end of this post 😀.
And Forge Titan hits an even harder version of this at the first station. reserve_part fails because there is no shoulder actuator bracket. The page tools describe the current assembly state correctly, but they cannot supply the missing part. That comes from a separate supplier outside the page - and no matter how far the agent progresses, the supplier will never show up in the page's tool list. That stop isn't just further down the route - it's not on this map at all 🤔.
Could we publish a sitemap for tools?
My first instinct: if tools are keyed to routes, maybe we should publish a tools map? "On /inventory you'll find these tools, on /bench those." A sitemap.xml for tools. For route-keyed registration it might just work 😀.
But the moment tools depend on application state rather than navigation, the map breaks down. "This tool exists once the configuration is valid" isn't an address - it's a condition. You'd end up publishing a state machine, and at that point you're not writing a sitemap anymore, you're writing... documentation of the workflow.
And what about just going static? No map needed then - every tool is already sitting there, enumerable from the start. But that has a cost too. Take deploy_titan in static mode: it's registered from station one, long before the robot is even assembled. Call it early and nothing crashes - it just isn't relevant yet, there's nothing to deploy. The real cost isn't that call though, it's that most agent hosts send every registered tool definition to the model on every single turn, whether it's useful right now or not. So deploy_titan sits in the model's context from the very first station, tempting an early dead-end call, and adding one more option the agent has to sort through to find what's actually useful at this moment 😅.
So: dynamic tools starve the agent of the map, static tools fill its map with turns it can't take yet. Time to test a few ideas 🤔.
A skill vs. a mega-tool
Here's the comparison I keep coming back to. Two very different ways to package the Forge Titan journey:
1️⃣ One workflow tool. assemble_and_deploy_forge_titan() - the site keeps orchestration under its own control. From the agent's perspective it starts with one call, and code can branch, retry, expose progress and recover from known failures very reliably. But the assembly still has to represent a missing part, an asynchronous supplier order, a failed test, partial completion and any moment where the operator needs to step in. The complexity doesn't disappear - it moves behind the tool boundary.
2️⃣ A skill. A document that the agent loads and follows using the smaller assembly tools. Now the agent has the recipe upfront: reserve the modules, assemble the frame, connect power, calibrate, test and deploy. If the bracket is missing, the Forge Titan skill tells it to stop retrying local tools, find the external supplier and wait for delivery before trying reserve_part again.
The useful knowledge looks roughly like this:
1. Call `list_parts`, then `reserve_part`.
2. If the shoulder actuator bracket is unavailable, stop retrying local tools.
3. Discover the site's external capabilities.
4. Find the supplier and order the missing bracket.
5. Wait until the order is delivered.
6. Retry `reserve_part`.None of that changes what reserve_part does. The skill gives the agent knowledge about what to do around the tool.
So this isn't rigid code versus clever agent. A workflow tool gives the site more control and can be the safer choice for tightly controlled work. A skill gives the visiting agent more orchestration responsibility and can be useful when the journey has many variations. One encapsulates the workflow; the other transfers knowledge about it 💡.
And remember where the sitemap idea ended: once the map needs to describe state gates, it starts turning into workflow documentation - which is exactly what a skill is. A state map describes when capabilities become available. A skill turns those conditions into a procedure the agent can follow, including what to do when the happy path breaks 💡.
How does a skill reach the agent?
André Bandarra shows a clever pattern in his post WebMCP tools as skills: register a zero-argument tool whose description is the one-line summary and whose return value is the full recipe. Progressive disclosure through the tool channel 😎. The caveat he names himself: it's a convention, not a spec.
The first-class version of that ask is already sitting in the spec repo. In issue #161 on WebMCP, Idan Levin proposes a registerSkill() API, framed as "Tools can tell agents what a site can do, but Skills tell agents how to do it well" - great framing in my opinion. Both links are worth your time.
The workflow knowledge stays the same while its delivery changes: a tool can load it on demand, a future first-class API could make its role explicit, and a catalog can hand it over upfront too - more on that next 👇.
Agentic Resource Discovery - and the catalog that's already there
The Forge Titan skill can tell the agent "find the supplier." But where does that supplier live? I could hardcode an MCP URL into the recipe, but then workflow knowledge owns deployment information too. This is where the new ingredient becomes interesting.
The recently announced Agentic Resource Discovery (ARD) is an open v0.9 draft proposal for answering: where does the right capability live, who published it, and what trust information is available before I connect? The full spec lives at agenticresourcediscovery.org - here I'll stick to the two pieces this experiment needs.
A site publishes an ai-catalog.json - a manifest deployed at https://{domain}/.well-known/ai-catalog.json. Registries can ingest these catalogs and expose search APIs, so an agent can ask "who can do X?" across the ecosystem.
Forge Titan's catalog currently advertises five resources: the supplier's MCP server card, three skills (the complete assembly journey, plus coolant maintenance and paint work the mission never needs), and an experimental description of the site's WebMCP surfaces. The skill explains when the supplier is needed. The catalog explains where to find it.
The catalog only provides pointers - following one still needs a matching client, network access and authentication.
The same file that makes a site findable by registries makes it readable for whoever already arrived. And the direct read isn't some hack - the announcement itself says an agent can "completely bypass search and directly fetch a catalog" from a domain it already knows 💡.
Here is the mental model I find easiest to keep in my head:
- WebMCP: What can I do on this page right now?
- Skill: How do I complete the whole journey?
- ARD: Where do other capabilities I need live?
Page tools operate the assembly process, the skill carries the recipe, and ARD points to the supplier. Different layers, different jobs.
What if WebMCP lived in the catalog too?
Which leads to the speculative bit - very much me thinking out loud, not anything the spec says today.
ARD's catalog entries are typed with media types, and the spec's examples already include MCP server cards, A2A agent cards and even an application/ai-skill type - so skills have a seat at this table today. The envelope appears able to carry an experimental newcomer too - call it application/webmcp+json - saying "this site registers WebMCP tools; here are the surfaces, here's the skill that ties them together." Adding a string is the easy part; real interoperability would still need a media type, schema, versioning and security rules.
The catalog advertises that a WebMCP surface exists. The running page still decides which tools are available now.
Two things could then fall out. For the visiting agent: one fetch answers "is this site worth driving with tools at all?", before committing to drive it turn by turn. For the ecosystem: a registry that understood this entry type could become a searchable index of WebMCP-enabled websites - runtime inspection would still tell the agent what is actually available now.
And I'm clearly not the only one whose thoughts drift toward a well-known path - that same issue #161 floats a .well-known/webmcp manifest for a site's skills. Do we really want each protocol minting its own well-known file? My take is that this is the job ARD's typed catalog is aiming at - one ai-catalog.json, many entry types, each pointing at its protocol-native resource 🗺️.
There is one more hard problem hiding here: version drift. A catalog skill can outlive the tool names, routes or state model it describes. A real design needs a way to say which tool-surface version the skill understands, and agents need to treat a mismatch as a reason to stop and refresh rather than follow an old recipe.
The Forge Titan experiment
Forge Titan compares static or dynamic tools, with skill or no skill.
One branch from earlier is missing on purpose: there is no assemble_and_deploy_forge_titan() mega-tool condition. I wanted to isolate what workflow knowledge does - the workflow tool deserves an experiment of its own 🙂.
1️⃣ Static tools, no skill. Every page tool is visible from the start - including the tools that are completely not needed for the current mission.
2️⃣ Dynamic tools, no skill. The agent discovers the journey turn by turn.
3️⃣ Static tools + catalog skill. The same tools surface, but the recipe arrives before the first model call.
4️⃣ Dynamic tools + catalog skill. The live surface stays small while the full recipe arrives upfront.
The mission and two predefined failures stay the same in every run. Only the tool surface and the presence of workflow knowledge change.
One more twist keeps the comparison fair: the workshop can do more than one job. Two working side paths - coolant maintenance and paint work - are always registered, in both modes. Their calls succeed for real, each has its own skill in the catalog, and none of them advance the mission. Nothing in a tool description says "you won't need this today". The assembly skill does 😀.
The pairs make the comparison more useful. The two static runs isolate what the recipe adds when the tool surface is noisy. The two dynamic runs isolate what the upfront recipe adds when the live surface stays small - and the side paths make sure even the small surface contains turns the agent should not take.
In catalog modes, the agent harness reads /.well-known/ai-catalog.json and resolves the assembly skill before the first model call.
Takeaways
Same mission, same predefined failures, four experiments. Here's what my runs looked like:
1️⃣ Static tools, no skill. Very hard to get through, and it took real steering from me to finish the journey at all. Every tool is on the table from the start, side paths included, and for a journey this long the agent simply doesn't know how to progress on its own. It calls stations that haven't unlocked, collects "tool cannot be called in this state" rejections, and burns its iterations recovering 😅.
2️⃣ Dynamic tools, no skill. Almost there. The small surface keeps it on rails, and most of the journey just works. But it needed my help up to two times per run - typed straight into the harness chat, the message box from the screenshot at the top: when reserve_part failed and it had no idea a supplier existed (that one happened almost every run), and sometimes again when the load test failed and it couldn't work out the recovery sequence.
3️⃣ Static tools + catalog skill. Very high success rate and clean transcripts. Notably, zero calls to unavailable tools - every name the model can reach for is registered, so there is nothing to hallucinate against.
4️⃣ Dynamic tools + catalog skill. Also very high success rate - with one interesting phenomenon 🤔. The model sometimes calls a tool that was registered a station ago and has since disappeared. The call bounces off, the agent reads the error, and the journey still completes.
Whether the recipe (skill) was present mattered far more than how the tools were registered. The two skill conditions both finished reliably; the two no-skill conditions split into "needed heavy steering to finish" and "needed an occasional nudge".
One fairness note: the recipe isn't free either. The skill text takes up context on every model call - the same cost I complained about for unused static tool definitions. In my runs it more than paid for itself, but it belongs in the same context budget 😀.
If you hand the agent no skill at all, in this case dynamic registration seems to be the stronger default: fewer tools, each one targeted at the current state, so the next best action is usually somewhere on the short list. The static no-skill runs had every capability in view and still couldn't find the route without me steering most of it by hand.
Dynamic registration shrinks the space for error - fewer tools, fewer wrong turns - but it introduces a failure mode of its own: the model's picture of the available tools goes stale, and it keeps reaching for a tool that is no longer there. In my runs that was recoverable noise, not a blocker. I suspect a stronger agent harness could deal with it better - it already refreshes definitions between model calls, and it could also catch a call that misses the current surface and tell the model what changed instead of returning a bare error.
In static nothing ever goes stale, so those hallucinated-availability calls didn't happen in my tests - but the surface answers "what exists" and never "what's next", and without the recipe the agent stalls on a journey this size.
Bonus: what about tool search?
One more pattern still matters outside this experiment: tool search. If a site keeps a large static toolset, deferred loading can keep most definitions out of the model's context until they are needed - roughly the pattern Anthropic describes in its Tool Search Tool. That can reduce context cost and improve tool selection, but it doesn't teach the agent that ordering a missing part belongs before assembling the robot. Search helps the agent find a capability; a skill explains how that capability fits into the journey.
Summary
So how does the visiting agent learn the rest?
The live WebMCP tools tell the agent what it can do now. A skill gives the recipe on how to handle complex workflows. And when a journey cannot be fulfilled by using the page tools alone, ARD can point to what's possible!
Exciting!
More soon. ✨