<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Loomcycle blog</title>
    <link>https://loomcycle.dev/blog/</link>
    <atom:link href="https://loomcycle.dev/blog/feed.xml" rel="self" type="application/rss+xml" />
    <description>Engineering writeups from the loomcycle project. Benchmark findings, architecture decisions, lessons learned.</description>
    <language>en-us</language>
    <copyright>Copyright 2026 Dennis Gubsky. Apache-2.0 licensed software; blog posts are All Rights Reserved unless noted otherwise.</copyright>
    <lastBuildDate>Tue, 26 May 2026 22:30:00 GMT</lastBuildDate>
    <ttl>1440</ttl>

    <item>
      <title>Multi-replica HA — the seven phases that get loomcycle close to v1.0</title>
      <link>https://loomcycle.dev/blog/multi-replica-ha-the-seven-phases.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/multi-replica-ha-the-seven-phases.html</guid>
      <pubDate>Tue, 26 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>Seven phases over four weeks took loomcycle from a single-process binary to a multi-replica cluster. Postgres LISTEN/NOTIFY backplane, cluster-wide per-user fairness, cross-replica cancel and pause/resume, advisory-lock singleton sweepers, DB-backed session locks and hooks. Two-replica docker-compose demo ships in the repo. Not v1.0 yet — load testing, functionality testing across the cluster matrix, and a hardening pass against cluster invariants are still ahead — but the biggest step toward it.</description>
    </item>

    <item>
      <title>What it took to make loomcycle a first-class n8n citizen</title>
      <link>https://loomcycle.dev/blog/loomcycle-meets-n8n.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/loomcycle-meets-n8n.html</guid>
      <pubDate>Mon, 25 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>@loomcycle/n8n-nodes-loomcycle went from v1.0.0 to v1.2.0 in four days. Five cluster sub-nodes including a LangChain Chat Model wired to loomcycle's gateway, two trigger nodes, six example workflows. The Tools Agent integration saga: bindTools, RunnableBinding, _getType detection, and a defence-in-depth synthetic tool_call_id at every wire boundary that took three patches to chase down.</description>
    </item>

    <item>
      <title>Becoming OpenAI-shaped without becoming OpenAI</title>
      <link>https://loomcycle.dev/blog/openai-shaped-without-becoming-openai.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/openai-shaped-without-becoming-openai.html</guid>
      <pubDate>Sun, 24 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>Loomcycle now serves three OpenAI-shaped endpoints: POST /v1/_llm/chat (loomcycle-native gateway, v0.11.0), POST /v1/chat/completions (Chat Completions shim, v0.11.3), and POST /v1/embeddings (Embeddings shim, v0.11.4). Every n8n Chat Model, LangChain consumer, RAG pipeline, and vector DB that defaults to OpenAI now works against your loomcycle by changing only the base URL and auth token. The interesting part isn't the wire format — it's what the shim deliberately omits, and what loomcycle adds that OpenAI doesn't.</description>
    </item>

    <item>
      <title>Scrubbing the model's incoming mail: a PostTool hook for WebFetch, WebSearch, and Brave</title>
      <link>https://loomcycle.dev/blog/scrub-before-the-model-sees-it.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/scrub-before-the-model-sees-it.html</guid>
      <pubDate>Sat, 23 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>A content-level prompt-injection defence built outside the model. WebFetch, WebSearch, and Brave Search results pass through a PostTool hook that scrubs sixteen injection patterns plus Cyrillic-homoglyph variants before reaching the agent's context. LIFO ordering with url-discovery, fail_mode: closed, and the JSON-nesting bypass that landed in production and got closed two hours later in review.</description>
    </item>

    <item>
      <title>When the agent is in one container and its definition is in another</title>
      <link>https://loomcycle.dev/blog/agents-across-the-container-wall.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/agents-across-the-container-wall.html</guid>
      <pubDate>Fri, 22 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>The historical loomcycle pattern read .claude/agents/*.md and .claude/skills/*/SKILL.md off a shared filesystem checkout. That breaks the moment the runtime and the app run in independent containers. We solved it with a substrate trio — AgentDef, SkillDef, MCPServerDef — each content-addressed by SHA-256 over a fixed field set, pushed at boot from the consumer's Docker image, resolved through one canonical lookup. With the cleanup-PR story of why the hash had to move from consumer-side to server-side.</description>
    </item>

    <item>
      <title>Even with no-training contracts, the LLM should never see your name</title>
      <link>https://loomcycle.dev/blog/the-llm-shouldnt-see-your-name.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/the-llm-shouldnt-see-your-name.html</guid>
      <pubDate>Tue, 19 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>Anthropic's no-training tier is a contractual promise about retention; it is not a reduction of what gets sent. We rebuilt the JobEmber data path so identifying PII never reaches the LLM at all — placeholders for names, emails, phones, and addresses; server-side comparison for location preferences via a narrow MCP tool — and dropped Read and HTTP from every agent that didn't strictly need them.</description>
    </item>

    <item>
      <title>What tools should an agent reading attacker HTML get? None.</title>
      <link>https://loomcycle.dev/blog/zero-tool-zero-secret-agent.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/zero-tool-zero-secret-agent.html</guid>
      <pubDate>Mon, 18 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>The job-posting-parser agent runs against attacker-controllable third-party HTML body text. We built it as the reference for the strictest profile we know how to ship: zero tools, zero secrets, tag-wrapped inputs, Zod-strict output. Each invariant covers a different failure mode; none is sufficient alone. Companion piece to the PII redaction post, frames a future deep-dive on content-level prompt-injection defence.</description>
    </item>

    <item>
      <title>Who decides which URLs an agent can visit? It's not the runtime.</title>
      <link>https://loomcycle.dev/blog/who-decides-which-urls-an-agent-can-visit.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/who-decides-which-urls-an-agent-can-visit.html</guid>
      <pubDate>Sun, 17 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>A Sunday-afternoon production-deploy test caught a structural gap in loomcycle's URL allowlist: pre-enumerated allowlists don't fit dynamic discovery, and the runtime doesn't have the context to fix that. We extended Pre-hooks with per-call host widening (v0.8.17), moving the decision out of loomcycle into the operator service that has the context to make it.</description>
    </item>

    <item>
      <title>The final bench scoreboard — 25 models, $21.92, all CAPABLE</title>
      <link>https://loomcycle.dev/blog/the-final-bench-scoreboard.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/the-final-bench-scoreboard.html</guid>
      <pubDate>Fri, 15 May 2026 10:00:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>Sweep #6 with v3 cases + multi-judge consensus across three provider families. Every model hit CAPABLE; the real signal is cost-per-pass and overall-pass count. ollama/deepseek-v4-pro topped both quality (0.91 semantic) and price ($0.0022/pass) — beating opus at 1/75 the cost.</description>
    </item>

    <item>
      <title>How we selected agent- and tool-capable models with our own benchmark</title>
      <link>https://loomcycle.dev/blog/how-we-selected-agent-and-tool-capable-models-with-own-benchmark.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/how-we-selected-agent-and-tool-capable-models-with-own-benchmark.html</guid>
      <pubDate>Thu, 14 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>We benchmarked five providers and all current flagship models for agentic tool-calling. Four sweeps in, we found a bug in our own bench harness that invalidated most of our conclusions. Here's what we learned, what the corrected findings actually say, and what's going into v2 of the bench.</description>
    </item>

    <item>
      <title>Our MCP server authenticated everyone as me</title>
      <link>https://loomcycle.dev/blog/our-mcp-server-authenticated-everyone-as-me.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/our-mcp-server-authenticated-everyone-as-me.html</guid>
      <pubDate>Tue, 12 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>We added MCP to fix one auth leak (typed schemas, bearer tokens out of the model's view) and quietly created another: a shared developer bearer that authorized every user's agent calls as the developer. Documents linked to the wrong user. The bug took a stretch of days and a persistent second user to find. Here's the story and the per-run bearer mechanism (v0.8.14) that fixed it.</description>
    </item>

    <item>
      <title>How I burned $80 on Claude Code in a Sunday afternoon</title>
      <link>https://loomcycle.dev/blog/the-80-dollars-i-burned-on-claude-code.html</link>
      <guid isPermaLink="true">https://loomcycle.dev/blog/the-80-dollars-i-burned-on-claude-code.html</guid>
      <pubDate>Thu, 07 May 2026 22:30:00 GMT</pubDate>
      <author>denn@loomcycle.dev (Dennis Gubsky)</author>
      <description>100 parallel claude code --print instances. MacBook Pro M1 fan at maximum. ANTHROPIC_API_KEY inherited via execve. Opus 4.7 on a dumb classification task. The bill: $80. Anthropic's robot denied reimbursement. The architectural lesson became loomcycle.</description>
    </item>
  </channel>
</rss>
