<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>sortie | Blog</title><description>Local-first web agents: natural-language goal in, real browser actions, schema-validated JSON out.</description><link>https://garrison-hq.github.io/</link><language>en</language><item><title>Introducing sortie: local-first web agents</title><link>https://garrison-hq.github.io/sortie/blog/introducing-sortie/</link><guid isPermaLink="true">https://garrison-hq.github.io/sortie/blog/introducing-sortie/</guid><description>sortie is an open-source, local-first platform for autonomous web agents — natural-language goal in, real browser actions, schema-validated JSON out. AGPL-licensed, runs entirely on your machine.

</description><pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A &lt;strong&gt;sortie&lt;/strong&gt; is a mission launched out from a garrison: go out, do the job, come back. That’s exactly what this tool does — you give it a goal, it ventures out onto the web in a real browser, and it comes back with structured data.&lt;/p&gt;
&lt;p&gt;sortie is an open-source, local-first platform for autonomous web agents. Describe the data you want in plain language plus a schema, and sortie drives a real Chromium browser, locates content by &lt;em&gt;meaning&lt;/em&gt; rather than brittle CSS/XPath selectors, and returns clean, schema-validated JSON. For multi-step tasks — “log in, search for X, collect the first 20 results” — an agent loop plans and executes navigation, clicks, typing, and pagination, recovering from failures along the way.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;why-local-first&quot;&gt;Why local-first&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Plenty of hosted services will run a browser fleet for you. sortie makes the opposite bet: &lt;strong&gt;everything runs on your machine.&lt;/strong&gt; Your sessions, your credentials, your scraped data — none of it transits someone else’s cloud.&lt;/p&gt;
&lt;p&gt;That choice shapes the security model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Credentials never reach the model.&lt;/strong&gt; Goals and traces only ever contain &lt;code dir=&quot;auto&quot;&gt;{{cred:NAME}}&lt;/code&gt; placeholders; substitution happens at the moment of typing, observations are scrubbed, and values are never persisted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Login sessions stay on disk.&lt;/strong&gt; Named profiles are stored at &lt;code dir=&quot;auto&quot;&gt;0600&lt;/code&gt; permissions, never enter the database, and are never returned by the API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bring your own LLM.&lt;/strong&gt; Anthropic, OpenAI, or any OpenAI-compatible endpoint — including a fully local Ollama or vLLM. With a local model and a SearXNG sidecar, the whole loop runs without a single external API call.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And one boundary worth stating plainly: &lt;strong&gt;CAPTCHA solving and anti-bot evasion are out of scope, permanently.&lt;/strong&gt; Runs that hit such walls fail gracefully with a clear reason. Be polite to the sites you automate.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-in-the-box&quot;&gt;What’s in the box&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLI&lt;/strong&gt; — &lt;code dir=&quot;auto&quot;&gt;extract&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;agent&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;search&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;fetch&lt;/code&gt;, saved &lt;code dir=&quot;auto&quot;&gt;query&lt;/code&gt; replays, login &lt;code dir=&quot;auto&quot;&gt;profile&lt;/code&gt; management, concurrent &lt;code dir=&quot;auto&quot;&gt;batch&lt;/code&gt; runs, and &lt;code dir=&quot;auto&quot;&gt;runs&lt;/code&gt; history/export.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Typed SDK&lt;/strong&gt; — zod schemas in, inferred types out.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;REST + WebSocket server&lt;/strong&gt; with a playground UI: author a run, watch it execute step by step with screenshots.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP server&lt;/strong&gt; — give Claude Code (or any MCP-capable agent) the web as an API: &lt;code dir=&quot;auto&quot;&gt;web_search&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;web_fetch&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;web_extract&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;run_agent&lt;/code&gt;, and more.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;open-source-agpl&quot;&gt;Open source, AGPL&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;sortie is &lt;a href=&quot;https://github.com/garrison-hq/sortie/blob/main/LICENSE&quot;&gt;AGPL-3.0&lt;/a&gt;: use it, modify it, self-host it freely — and if you run a modified version as a service, share your changes under the same terms.&lt;/p&gt;
&lt;p&gt;The code is on GitHub at &lt;a href=&quot;https://github.com/garrison-hq/sortie&quot;&gt;garrison-hq/sortie&lt;/a&gt;. Start with the &lt;a href=&quot;https://garrison-hq.github.io/sortie/getting-started/&quot;&gt;getting started guide&lt;/a&gt;, and come say hi in the issues if you build something with it — or if something breaks.&lt;/p&gt;</content:encoded><category>announcement</category></item></channel></rss>