<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: capman</title>
    <description>The latest articles on DEV Community by capman (@capman_engine).</description>
    <link>https://dev.to/capman_engine</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3841813%2F13ee932e-3605-4bd1-a89e-a9c63afb52df.png</url>
      <title>DEV Community: capman</title>
      <link>https://dev.to/capman_engine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/capman_engine"/>
    <language>en</language>
    <item>
      <title>Beyond Browser Automation: How Teams Are Actually Solving Agent Reliability</title>
      <dc:creator>capman</dc:creator>
      <pubDate>Thu, 11 Jun 2026 19:19:39 +0000</pubDate>
      <link>https://dev.to/capman_engine/beyond-browser-automation-how-teams-are-actually-solving-agent-reliability-2ea8</link>
      <guid>https://dev.to/capman_engine/beyond-browser-automation-how-teams-are-actually-solving-agent-reliability-2ea8</guid>
      <description>&lt;p&gt;AI agents are becoming increasingly capable, yet many production failures have nothing to do with intelligence. A button moves, a modal appears, a page loads differently, and an automation that worked yesterday suddenly breaks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzj1z5w0en0a7fga2hud9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzj1z5w0en0a7fga2hud9.png" alt=" " width="796" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This raises an important question: is browser automation the right abstraction for reliable AI systems?&lt;/p&gt;

&lt;p&gt;As teams move beyond demos and into production, many are exploring alternatives such as APIs, tool ecosystems, workflow engines, and hybrid architectures. What's emerging isn't a single winning approach, but a broader shift toward building AI systems that prioritize reliability over novelty.&lt;/p&gt;




&lt;h1&gt;
  
  
  Stage 1: Browser Automation
&lt;/h1&gt;

&lt;p&gt;For many teams, browser automation is the natural starting point.&lt;br&gt;
The philosophy is simple: If humans can perform a task through a UI, AI should be able to do the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hp57lgp6pckszfcr50r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hp57lgp6pckszfcr50r.png" alt=" " width="796" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Frameworks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pptr.dev/" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;make this surprisingly easy.&lt;/p&gt;

&lt;p&gt;This is also the philosophy behind many recent "computer-use" agents. The appeal is obvious.&lt;/p&gt;

&lt;p&gt;No APIs.&lt;br&gt;
No integration work.&lt;br&gt;
Just use the application exactly like a human would.&lt;/p&gt;

&lt;p&gt;But over time, many teams discover that they're not trying to automate browsers. They're trying to automate systems. And the browser simply happens to sit in the middle.&lt;/p&gt;

&lt;p&gt;As reliability becomes important, that extra layer starts to feel increasingly expensive.&lt;/p&gt;




&lt;h1&gt;
  
  
  Stage 2: Moving Closer to the Source
&lt;/h1&gt;

&lt;p&gt;Many teams eventually realize that communicating directly with systems is fundamentally simpler than navigating interfaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7okche1m6sfblwi2uhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7okche1m6sfblwi2uhj.png" alt=" " width="798" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where is the button?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;they start asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Which operation should be executed?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the philosophy behind platforms like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.stripe.com/api" rel="noopener noreferrer"&gt;Stripe API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/rest" rel="noopener noreferrer"&gt;GitHub REST API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.slack.com/" rel="noopener noreferrer"&gt;Slack API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shopify.dev/docs/api" rel="noopener noreferrer"&gt;Shopify API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The shift may seem small, but it removes entire categories of failures.&lt;/p&gt;

&lt;p&gt;No screenshots.&lt;br&gt;
No waiting for pages.&lt;br&gt;
No brittle selectors.&lt;br&gt;
No UI redesign problems.&lt;/p&gt;




&lt;h1&gt;
  
  
  Stage 3: Tool Ecosystems
&lt;/h1&gt;

&lt;p&gt;As integrations multiply, another problem begins to emerge.&lt;br&gt;
Tool sprawl.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1z23npovc42vwhskg68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1z23npovc42vwhskg68.png" alt=" " width="800" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One integration becomes ten.&lt;br&gt;
Ten become hundreds.&lt;br&gt;
Eventually, selecting the right capability becomes harder than executing it.&lt;/p&gt;

&lt;p&gt;This is partly why protocols such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://claude.ai/download" rel="noopener noreferrer"&gt;Claude Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://smithery.ai/" rel="noopener noreferrer"&gt;Smithery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://composio.dev/" rel="noopener noreferrer"&gt;Composio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;have attracted so much attention recently.&lt;/p&gt;

&lt;p&gt;They focus on making tools easier to expose and consume. Ironically, solving interface navigation introduces a new kind of navigation problem:&lt;/p&gt;

&lt;p&gt;Capability navigation.&lt;/p&gt;




&lt;h1&gt;
  
  
  Stage 4: The Return of Workflows
&lt;/h1&gt;

&lt;p&gt;Another interesting trend is the resurgence of workflow engines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99exdflj55xr1l4rk6xy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99exdflj55xr1l4rk6xy.png" alt=" " width="797" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://n8n.io/" rel="noopener noreferrer"&gt;n8n&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zapier.com/" rel="noopener noreferrer"&gt;Zapier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.make.com/" rel="noopener noreferrer"&gt;Make&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://temporal.io/" rel="noopener noreferrer"&gt;Temporal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;embrace a different philosophy.&lt;/p&gt;

&lt;p&gt;Instead of giving agents unlimited freedom, they constrain them inside predictable flows. This may sound less exciting. But production systems often value predictability more than autonomy. Users don't care how creative your architecture is.&lt;/p&gt;

&lt;p&gt;They care whether it works.&lt;/p&gt;




&lt;h1&gt;
  
  
  Stage 5: Hybrid Architectures
&lt;/h1&gt;

&lt;p&gt;Perhaps the most interesting trend is that many teams seem to be combining everything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyuog6qrhcvyx2llowx4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyuog6qrhcvyx2llowx4v.png" alt=" " width="800" height="1097"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Increasingly, reliability seems to come from layers rather than a single technology.&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use APIs whenever possible.&lt;/li&gt;
&lt;li&gt;Fall back to browser automation when necessary.&lt;/li&gt;
&lt;li&gt;Escalate uncertain situations to humans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This philosophy is visible across many modern agent frameworks, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://langchain-ai.github.io/langgraph/" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://microsoft.github.io/autogen/" rel="noopener noreferrer"&gt;AutoGen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.crewai.com/" rel="noopener noreferrer"&gt;CrewAI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;Google ADK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's interesting is that browser automation doesn't disappear.&lt;/p&gt;

&lt;p&gt;It simply becomes a fallback rather than the default. And perhaps that's the biggest lesson I'm seeing across the ecosystem. Reliable systems aren't replacing one approach with another. They're layering multiple approaches together&lt;/p&gt;




&lt;p&gt;GitHub: &lt;a href="https://github.com/Hobbydefiningdoctory/capman" rel="noopener noreferrer"&gt;github.com/Hobbydefiningdoctory/capman&lt;/a&gt;&lt;br&gt;
Capman-site: &lt;a href="https://capman.qzz.io" rel="noopener noreferrer"&gt;capman&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;capman v0.6.2 — TypeScript, MIT licence, dual CJS/ESM, zero runtime dependencies beyond zod.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why Teaching AI to Click Buttons Is a Broken Abstraction</title>
      <dc:creator>capman</dc:creator>
      <pubDate>Tue, 09 Jun 2026 23:02:57 +0000</pubDate>
      <link>https://dev.to/capman_engine/why-teaching-ai-to-click-buttons-is-a-broken-abstraction-5ecd</link>
      <guid>https://dev.to/capman_engine/why-teaching-ai-to-click-buttons-is-a-broken-abstraction-5ecd</guid>
      <description>&lt;p&gt;We've all experienced it.&lt;/p&gt;

&lt;p&gt;You automate a repetitive workflow, only for everything to break because someone moved a button or redesigned a page. Surprisingly, many AI agents suffer from the exact same problem.&lt;/p&gt;

&lt;p&gt;Instead of understanding the underlying task, they're often forced to interact with software the same way humans do: by clicking buttons, reading screens, and navigating menus.&lt;/p&gt;

&lt;p&gt;This approach works.&lt;br&gt;
But it raises an important question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Are we teaching AI systems to solve problems, or are we simply teaching them to use software designed for humans?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By the end of this article, we'll explore why UI navigation has become one of the biggest bottlenecks in AI agents and why many developers believe the industry is solving the wrong problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Task Isn't Really Simple
&lt;/h2&gt;

&lt;p&gt;Imagine someone wants to check the status of an order.&lt;/p&gt;

&lt;p&gt;For a browser-based AI agent, the process might look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3r56z3hnyestewknrze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3r56z3hnyestewknrze.png" alt=" " width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What seems like a simple request actually requires multiple steps. And every step introduces opportunities for failure.&lt;/p&gt;




&lt;h2&gt;
  
  
  The UI Was Built For Humans
&lt;/h2&gt;

&lt;p&gt;Graphical user interfaces exist because humans need visual representations of information. Buttons, menus, and forms are abstractions created for us.&lt;/p&gt;

&lt;p&gt;Computers themselves don't need buttons.&lt;/p&gt;

&lt;p&gt;Yet many modern AI agents spend enormous amounts of computation trying to interpret screenshots, locate interface elements, and simulate mouse clicks.&lt;br&gt;
They're essentially pretending to be humans.&lt;/p&gt;




&lt;h2&gt;
  
  
  We've Seen This Problem Before
&lt;/h2&gt;

&lt;p&gt;In Robotic Process Automation (RPA). Large enterprises invested heavily in automation workflows that depended on screen layouts and specific button locations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i17yllmyl236jg06z1j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7i17yllmyl236jg06z1j.jpg" alt=" " width="799" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then a website redesign happened.&lt;br&gt;
Or a menu moved.&lt;br&gt;
Or a label changed.&lt;/p&gt;

&lt;p&gt;And suddenly entire workflows stopped working.&lt;/p&gt;

&lt;p&gt;Fragile automation became one of the biggest challenges facing RPA systems.&lt;br&gt;
Many AI agents are repeating the same pattern—only with language models replacing traditional scripts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Browser Agents Pay a Heavy Price
&lt;/h2&gt;

&lt;p&gt;Research from companies building browser agents has also highlighted challenges such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow execution&lt;/li&gt;
&lt;li&gt;Increased token costs&lt;/li&gt;
&lt;li&gt;Fragility&lt;/li&gt;
&lt;li&gt;Ambiguous actions&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbr5njct0mdr9rbgxkzf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbr5njct0mdr9rbgxkzf.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Industry Is Optimizing The Wrong Layer
&lt;/h2&gt;

&lt;p&gt;Today's AI systems are incredibly powerful.&lt;/p&gt;

&lt;p&gt;Yet some of them spend most of their time performing tasks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finding buttons.&lt;/li&gt;
&lt;li&gt;Waiting for pages to load.&lt;/li&gt;
&lt;li&gt;Reading screenshots.&lt;/li&gt;
&lt;li&gt;Navigating menus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't the user's actual goals.&lt;br&gt;
Users don't want a button clicked.&lt;br&gt;
Users want a problem solved.&lt;br&gt;
There's a difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Irony
&lt;/h2&gt;

&lt;p&gt;Humans navigate interfaces because we have no alternative.&lt;/p&gt;

&lt;p&gt;Machines do.&lt;/p&gt;

&lt;p&gt;And yet we're investing enormous amounts of compute teaching AI systems how to behave like users instead of asking whether user interfaces are even the right abstraction for machines.&lt;/p&gt;

&lt;p&gt;The result is an interesting paradox:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Some of the world's most advanced AI models spend their time doing something web browsers have been doing since the 1990s.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;GitHub: &lt;a href="https://github.com/Hobbydefiningdoctory/capman" rel="noopener noreferrer"&gt;github.com/Hobbydefiningdoctory/capman&lt;/a&gt;&lt;br&gt;
Capman-site: &lt;a href="https://capman.qzz.io" rel="noopener noreferrer"&gt;capman&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;capman v0.6.2 — TypeScript, MIT licence, dual CJS/ESM, zero runtime dependencies beyond zod.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>machinelearning</category>
      <category>automation</category>
    </item>
    <item>
      <title>Capman: Stop Routing Every Intent Through an LLM</title>
      <dc:creator>capman</dc:creator>
      <pubDate>Sun, 12 Apr 2026 10:31:26 +0000</pubDate>
      <link>https://dev.to/capman_engine/capman-stop-routing-every-intent-through-an-llm-5jc</link>
      <guid>https://dev.to/capman_engine/capman-stop-routing-every-intent-through-an-llm-5jc</guid>
      <description>&lt;p&gt;Most AI apps send every user message to a language model — even when the intent is completely predictable. capman intercepts the 80% you already know how to answer, resolves them in under 2 ms at zero token cost, and lets the LLM handle only the queries that genuinely need it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When a user types &lt;code&gt;"what time is it?"&lt;/code&gt; into your AI app, this is what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User input
  → serialize message
  → HTTP request to LLM API     ← 800–1500 ms
  → token cost (~$0.001–$0.01)
  → parse function call JSON
  → invoke time handler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You paid an LLM to decode &lt;code&gt;"what time is it"&lt;/code&gt; into a clock call. It knew the answer in 1 ms. You waited 1,200 ms anyway.&lt;/p&gt;

&lt;p&gt;Standard function calling routes &lt;strong&gt;every&lt;/strong&gt; query through the model — by design. For ambiguous, open-ended input, that's the right call. For well-defined intents like "check availability", "go to settings", or "get my orders", it's pure overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is capman?
&lt;/h2&gt;

&lt;p&gt;capman is a TypeScript library that sits in front of your LLM. It reads a &lt;strong&gt;capability manifest&lt;/strong&gt; — a machine-readable list of everything your app can do — and matches user queries against it using weighted keyword scoring.&lt;/p&gt;

&lt;p&gt;If it finds a confident match: it resolves the query directly. No LLM. No network. No tokens.&lt;br&gt;
If it doesn't: it escalates to your LLM automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readManifest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;capman&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;readManifest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;balanced&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// keyword-first, LLM only when needed&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;callYourLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Check availability for blue jacket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;capability&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// 'check_product_availability'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolvedVia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;// 'keyword' | 'llm' | 'cache'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;totalMs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;// 1.6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vz3k8qj838s3hadw46i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vz3k8qj838s3hadw46i.png" alt="Step-by-step pipeline: Input → Cache → Keyword Scorer → Privacy Check → Resolver → Learning" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;engine.ask()&lt;/code&gt; call passes through six steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cache check&lt;/strong&gt; — normalized query key lookup. Hit → return in &amp;lt;1 ms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Keyword scorer&lt;/strong&gt; — every capability in your manifest is scored 0–100 across three weighted sources:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Example sentences&lt;/td&gt;
&lt;td&gt;60 pts&lt;/td&gt;
&lt;td&gt;Strongest — direct intent overlap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capability description&lt;/td&gt;
&lt;td&gt;30 pts&lt;/td&gt;
&lt;td&gt;Secondary — synonym coverage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capability name&lt;/td&gt;
&lt;td&gt;10 pts&lt;/td&gt;
&lt;td&gt;Weakest — tiebreaker only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. Branch decision&lt;/strong&gt; — confidence ≥ 50%? Direct resolve. Below threshold? LLM escalation (rate-limited + circuit-breaker protected).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Privacy enforcement&lt;/strong&gt; — &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;user_owned&lt;/code&gt;, or &lt;code&gt;admin&lt;/code&gt; checked before any API call fires.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Resolver&lt;/strong&gt; — &lt;code&gt;api&lt;/code&gt; (fetch + retry + timeout), &lt;code&gt;nav&lt;/code&gt; (URL template), or &lt;code&gt;hybrid&lt;/code&gt; (both in parallel).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Learning + trace&lt;/strong&gt; — full &lt;code&gt;ExecutionTrace&lt;/code&gt; returned with step-by-step timing. Pre-boost result recorded to prevent feedback loops.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Modes, One Decision
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cheap      → keyword only, &amp;lt;2 ms, $0 — for high-volume known intents
balanced   → keyword first, LLM if &amp;lt;50% confidence — default
accurate   → LLM first, keyword fallback — for ambiguous open input
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mode is set per-engine instance. Switch by swapping the constructor option.&lt;/p&gt;




&lt;h2&gt;
  
  
  capman vs Standard Function Calling
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbabg7dzxycef87g4sciw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbabg7dzxycef87g4sciw.png" alt="Side-by-side step flow: LLM path vs capman path for the same query" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The fundamental difference is &lt;strong&gt;when&lt;/strong&gt; the LLM is involved:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;LLM Function Calling&lt;/th&gt;
&lt;th&gt;capman&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Latency&lt;/td&gt;
&lt;td&gt;800–1,500 ms&lt;/td&gt;
&lt;td&gt;&amp;lt;2 ms (direct)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token cost&lt;/td&gt;
&lt;td&gt;~$0.001–$0.01/call&lt;/td&gt;
&lt;td&gt;$0 on direct match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure rate&lt;/td&gt;
&lt;td&gt;~25% (hallucinations, timeouts)&lt;/td&gt;
&lt;td&gt;0% on direct match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy enforcement&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Built-in per capability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caching&lt;/td&gt;
&lt;td&gt;External setup&lt;/td&gt;
&lt;td&gt;Memory / File / Combo built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tracing&lt;/td&gt;
&lt;td&gt;Custom logging needed&lt;/td&gt;
&lt;td&gt;Automatic on every call&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;capman doesn't replace your LLM — it protects it. The model gets fewer calls, better-framed prompts, and none of the deterministic work it was doing before.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo: The Weather Query
&lt;/h2&gt;

&lt;p&gt;The demo runs a battle test: the same query submitted three times in a row, both engines running in parallel. Here's what came back.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Query
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"what is the weather"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxuh2l83abodufonzsbn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxuh2l83abodufonzsbn.png" alt="Bar chart: LLM 1151ms / 851ms / 931ms vs capman 1.61ms / 0.59ms / 0.78ms across 3 rounds" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Round 1 — cold start:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLM: &lt;code&gt;1,151.17 ms&lt;/code&gt; ✓ Success → correct tool&lt;/li&gt;
&lt;li&gt;capman: &lt;code&gt;1.61 ms&lt;/code&gt; — matched &lt;code&gt;"weather"&lt;/code&gt; exactly — &lt;strong&gt;715× faster&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Round 2 — learning kicks in (+1 pt boost):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLM: &lt;code&gt;851.51 ms&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;capman: &lt;code&gt;0.59 ms&lt;/code&gt; — boost applied from prior hit — &lt;strong&gt;1,443× faster&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Round 3 — boost grows (+2 pts):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLM: &lt;code&gt;931.02 ms&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;capman: &lt;code&gt;0.78 ms&lt;/code&gt; — &lt;strong&gt;1,193× faster&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzqnflusoggpl42kyadri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzqnflusoggpl42kyadri.png" alt="Learning timeline: Round 1→2→3→max, showing boost, confidence, latency columns" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Does the Latency Drop on Rounds 2 and 3?
&lt;/h3&gt;

&lt;p&gt;The learning store tracks &lt;code&gt;keyword → capability → hitCount&lt;/code&gt;. On each successful match, it builds a boost index. On the next call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;boost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="err"&gt;₂&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hitCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More hits → logarithmically larger boost → capability scores higher faster → match resolves sooner in the scorer loop. The cap is +15 points total. The pre-boost result is what gets recorded (not the post-boost result) — this prevents a feedback loop where boosted winners accumulate hits and permanently displace keyword matches.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Capability Definition
&lt;/h2&gt;

&lt;p&gt;Everything capman does flows from a structured manifest. Here's a full capability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// capman.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.my-store.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;check_product_availability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Check product availability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Check stock and pricing for a product by name or ID.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Is the blue jacket in stock?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Check availability for product 42&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do you have size M?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Product name or ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// extracted from the query&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;variants&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products/{product}/availability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;privacy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx capman generate   &lt;span class="c"&gt;# → manifest.json&lt;/span&gt;
npx capman validate   &lt;span class="c"&gt;# → check all capabilities&lt;/span&gt;
npx capman demo       &lt;span class="c"&gt;# → live test with sample queries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What capman Does Not Replace
&lt;/h2&gt;

&lt;p&gt;capman handles the routing layer. It doesn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate creative responses&lt;/li&gt;
&lt;li&gt;Summarize or reason over content&lt;/li&gt;
&lt;li&gt;Handle open-ended questions with no predictable shape&lt;/li&gt;
&lt;li&gt;Replace conversational context management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For any of those, the LLM still runs — capman just makes sure it runs &lt;strong&gt;only when it needs to&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;capman
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx capman init       &lt;span class="c"&gt;# create capman.config.js&lt;/span&gt;
npx capman generate   &lt;span class="c"&gt;# generate manifest.json&lt;/span&gt;
npx capman run &lt;span class="s2"&gt;"your query"&lt;/span&gt; &lt;span class="nt"&gt;--debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/Hobbydefiningdoctory/capman" rel="noopener noreferrer"&gt;github.com/Hobbydefiningdoctory/capman&lt;/a&gt;&lt;br&gt;
Capman-site: &lt;a href="https://capman.qzz.io" rel="noopener noreferrer"&gt;capman&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;capman v0.4.5 — TypeScript, MIT licence, dual CJS/ESM, zero runtime dependencies beyond zod.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>typescript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a tool that lets AI agents interact with your app without navigating the UI</title>
      <dc:creator>capman</dc:creator>
      <pubDate>Mon, 30 Mar 2026 19:43:21 +0000</pubDate>
      <link>https://dev.to/capman_engine/i-built-a-tool-that-lets-ai-agents-interact-with-your-app-without-navigating-the-ui-1g82</link>
      <guid>https://dev.to/capman_engine/i-built-a-tool-that-lets-ai-agents-interact-with-your-app-without-navigating-the-ui-1g82</guid>
      <description>&lt;p&gt;When I started thinking about how AI agents interact with applications, something bothered me.&lt;/p&gt;

&lt;p&gt;Today, when an AI agent needs to answer &lt;em&gt;"are there seats available for Friday?"&lt;/em&gt; — it navigates your app like a tourist with no map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI clicks → Home → Explore → Events → Category → Availability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's slow, wasteful, and it exposes parts of your app the AI was never supposed to see.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;capman&lt;/strong&gt; — a Capability Manifest Engine that gives AI agents a structured map of what your app can do, and shows you exactly why it made every decision.&lt;/p&gt;




&lt;h2&gt;
  
  
  The core idea
&lt;/h2&gt;

&lt;p&gt;Your app publishes a &lt;strong&gt;capability manifest&lt;/strong&gt; — a machine-readable list of everything it can do, what API to call, and what data scope is allowed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// capman.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.my-app.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;check_availability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Check availability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Check if a product or slot is available on a given date.',&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;examples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Are there seats available Friday?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Check availability for blue jacket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Item name or ID', required: true,  source: 'user_query' },&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Date to check',   required: false, source: 'user_query' },&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/availability/{item}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;privacy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI reads this manifest and goes directly to the answer — no navigation, no guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part I'm most proud of: the execution trace
&lt;/h2&gt;

&lt;p&gt;Every query returns a full execution trace. No black box.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.my-app.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Are there seats available Friday?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// {&lt;/span&gt;
&lt;span class="c1"&gt;//   query: 'Are there seats available Friday?',&lt;/span&gt;
&lt;span class="c1"&gt;//   candidates: [&lt;/span&gt;
&lt;span class="c1"&gt;//     { capabilityId: 'check_availability', score: 100, matched: true  },&lt;/span&gt;
&lt;span class="c1"&gt;//     { capabilityId: 'get_orders',         score: 12,  matched: false },&lt;/span&gt;
&lt;span class="c1"&gt;//     { capabilityId: 'navigate_to_screen', score: 0,   matched: false },&lt;/span&gt;
&lt;span class="c1"&gt;//   ],&lt;/span&gt;
&lt;span class="c1"&gt;//   reasoning: [&lt;/span&gt;
&lt;span class="c1"&gt;//     'Matched "check_availability" with 100% confidence',&lt;/span&gt;
&lt;span class="c1"&gt;//     'Rejected: get_orders (12%)',&lt;/span&gt;
&lt;span class="c1"&gt;//     'Resolved via: keyword',&lt;/span&gt;
&lt;span class="c1"&gt;//     'Extracted params: item=seats, date=Friday',&lt;/span&gt;
&lt;span class="c1"&gt;//   ],&lt;/span&gt;
&lt;span class="c1"&gt;//   steps: [&lt;/span&gt;
&lt;span class="c1"&gt;//     { type: 'cache_check',   status: 'miss', durationMs: 0 },&lt;/span&gt;
&lt;span class="c1"&gt;//     { type: 'keyword_match', status: 'pass', durationMs: 1, detail: 'confidence: 100%' },&lt;/span&gt;
&lt;span class="c1"&gt;//     { type: 'privacy_check', status: 'pass', durationMs: 0, detail: 'level: public'    },&lt;/span&gt;
&lt;span class="c1"&gt;//     { type: 'resolve',       status: 'pass', durationMs: 2, detail: 'via api'          },&lt;/span&gt;
&lt;span class="c1"&gt;//   ],&lt;/span&gt;
&lt;span class="c1"&gt;//   totalMs: 4,&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This answers the question every AI developer eventually asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Why did it pick this capability?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"Why wrong parameters?"&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"Why did it fail?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today with LangChain, OpenAI function calling, or custom agents — there's no clear answer. Logs are scattered, debugging is painful.&lt;/p&gt;

&lt;p&gt;capman makes AI execution debuggable like backend code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three matching modes — control cost vs accuracy
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cheap — keyword only, free, fast&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cheap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// balanced — keyword first, LLM fallback if confidence &amp;lt; 50% (default)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;balanced&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myLLM&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// accurate — LLM first, always correct&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accurate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myLLM&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM function is plug-and-play — works with Anthropic, OpenAI, or any model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;balanced&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Privacy enforcement — per capability, not per request
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get_my_orders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;privacy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_owned&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// blocked without auth&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get_admin_report&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;privacy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;       &lt;span class="c1"&gt;// blocked without admin role&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass auth context once — capman enforces it before resolution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CapmanEngine&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isAuthenticated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// auto-injected into session params&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  See it live in 30 seconds
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx capman demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That runs a live demo against a sample e-commerce app — no config needed. You'll see matched capabilities, execution traces, candidate scores, and API calls constructed in real time.&lt;/p&gt;

&lt;p&gt;Or run a query against your own manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx capman init          &lt;span class="c"&gt;# creates capman.config.js&lt;/span&gt;
npx capman generate      &lt;span class="c"&gt;# generates manifest.json&lt;/span&gt;
npx capman run &lt;span class="s2"&gt;"are there seats available Friday?"&lt;/span&gt; &lt;span class="nt"&gt;--debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;capman
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/Hobbydefiningdoctory/capman" rel="noopener noreferrer"&gt;github.com/Hobbydefiningdoctory/capman&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;a href="https://npmjs.com/package/capman" rel="noopener noreferrer"&gt;npmjs.com/package/capman&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capman-site&lt;/strong&gt;: &lt;a href="https://capman.qzz.io" rel="noopener noreferrer"&gt;capman&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;capman v0.4.5 — TypeScript, MIT licence, dual CJS/ESM, zero runtime dependencies beyond zod.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
