Engineering writeups.
Benchmark findings, architecture decisions, and lessons learned from building loomcycle. We post when we have something useful to share — not on a schedule. Subscribe via RSS if you want to know when that happens.
-
Multi-replica HA — the seven phases that get loomcycle close to v1.0
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 + pause/resume, advisory-lock singleton sweepers, DB-backed session locks and hooks. Two-replica
docker-composedemo ships in the repo. Not v1.0 yet — load testing and hardening still ahead — but the biggest step toward it. -
What it took to make loomcycle a first-class n8n citizen
@loomcycle/n8n-nodes-loomcyclewent 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, six action nodes covering Run / Memory / Channel and the AgentDef / SkillDef / MCPServerDef substrate. Plus the Tools Agent integration saga — three patches into the@langchain/core/messages/ai.js:178rejection trail, ending with a defence-in-depth synthetictool_call_idat every wire boundary. -
Becoming OpenAI-shaped without becoming OpenAI
Loomcycle grew an OpenAI-shaped front door this week. Three releases:
POST /v1/_llm/chat(the loomcycle-native gateway, v0.11.0),POST /v1/chat/completions(the Chat Completions shim, v0.11.3), andPOST /v1/embeddings(the 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. The interesting part is what the shim deliberately doesn't translate. -
Scrubbing the model's incoming mail: a PostTool hook for WebFetch, WebSearch, and Brave
A content-level prompt-injection defence built outside the model. WebFetch, WebSearch, and Brave Search results now pass through a PostTool hook that scrubs sixteen injection patterns plus Cyrillic-homoglyph variants before reaching the agent's context. The interesting parts: LIFO ordering with url-discovery,
fail_mode: closed, and the JSON-nesting bypass we shipped and closed within two hours. -
When the agent is in one container and its definition is in another
The historical loomcycle pattern read
.claude/agents/*.mdoff a shared filesystem checkout. That dies 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 set of fields, pushed at boot from the consumer's image, resolved through one canonical lookup. With the cleanup-PR story of why the hash had to move from consumer-side to server-side. -
Even with no-training contracts, the LLM should never see your name
Anthropic's no-training tier is a promise about retention, 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
ReadandHTTPfrom every agent that didn't strictly need them. -
What tools should an agent reading attacker HTML get? None.
Companion piece to the PII post. The
job-posting-parseragent runs against attacker-controllable third-party HTML and was built for the smallest-possible blast radius: zero tools, zero secrets, tag-wrapped inputs, Zod-strict output. Each invariant covers a different failure mode; none is sufficient alone. Frames a future deep-dive on content-level prompt-injection defence. -
Who decides which URLs an agent can visit? It's not the runtime.
A Sunday-afternoon production-deploy test caught a structural gap: agents that find URLs via
WebSearchcan't fetch them, because the URL allowlist is pre-enumerated and discovery isn't. The runtime doesn't have the context to make the per-URL call — only the consumer service does. We extended Pre-hooks with per-call host widening (v0.8.17), moving the decision out of loomcycle while keeping the security boundary intact. -
The final bench scoreboard — 25 models, $21.92, all CAPABLE
Sweep #6 with v3 cases + multi-judge consensus across three provider families. Every model passed. The real signal moved to cost-per-pass and overall-pass count.
ollama/deepseek-v4-protopped both quality (0.91 semantic) and price ($0.0022/pass) — beating opus at 1/75 the cost. Anthropic models are now the three most expensive in the 25-model field. -
How we selected agent- and tool-capable models with our own benchmark
We ran a benchmark sweep across five providers to find models suitable for agentic tool-calling — and discovered, four sweeps in, that the bench harness itself had a bug invalidating most of our conclusions. Here's what we learned, what the corrected findings actually say, and what's going into v2 of the bench.
-
Our MCP server authenticated everyone as me
We added MCP to fix one auth leak — typed schemas, bearer tokens out of the model's view — and quietly created another. The shared developer bearer that authorized our MCP server resolved every user's agent calls to my user_id. Documents got 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.
-
How I burned $80 on Claude Code in a Sunday afternoon
A parallel-spawn loop. 100
claude code --printinstances. MacBook Pro M1 fan at maximum. MyANTHROPIC_API_KEYinherited viaexecve. Opus 4.7 on a dumb classification task. The bill: $80. Anthropic's robot denied reimbursement. The architectural lesson became loomcycle.