What changed in the services in the first half of October, why each change matters, and what it improves for the people who run AI agents and pay for them. It is grouped by the problem each change solves, not by repository, because most problems were solved by several services moving together. Each service's own list is at the end, under its name.
repositories changed
pull requests merged
release tags
new numbered rules in TokenFuse, CostCrew and Wardryx
day of deliberate failure on two clouds, a home server and two routers
Across 24 repositories we merged 532 pull requests (794 commits without merges) and cut 86 release tags. TokenFuse moved from 1.4.1 to 1.14.0, Wardryx from 1.1.3 to 1.5.0, CostCrew from 0.2.2 to 0.6.0 and Heraldyx from 0.2.5 to 0.7.0, and the two launchers shipped 45 releases between them to carry those versions to real machines.
How these were counted. Releases count tags created between 1 and 15 October; "on main" means merged but not yet in a tagged release. Counts were read from each repository's main branch and its merged pull requests on 15 October.
Each theme opens with the problem in plain words, then lists what changed, then says why it matters for someone who runs agents and owns their cost. A short line at the end names the versions.
Most services released in two bursts: on 4 October, when the shared library, the typed risk signal and the source checks moved together, and from 12 to 15 October, when the work on retained money, tool safety and the failure day landed. The launchers, stack-single for one machine and stack-k8s for a cluster, release whenever a service they carry moves, which is why they lead the count.
The speed is only useful because of the method behind it, and the method is the part a reviewer can check. Every change follows the same loop.
A gateway that enforces budgets is only as good as its price book. When the book did not know a model, the call was charged at a deliberately high fallback rate, USD 15 per million input tokens and 75 per million output. That is safe for a budget, because it never under-counts. It is wrong for a report, because finance reconciles against the invoice and the invoice uses the list rate.
openai/... are priced at OpenAI's list rate. The rows cite the vendor page they were read from and the date.x_price_basis column says known or fallback). A gateway shows the book it charges with, and an operator can supply prices in a file.In FinOps the invoice is the source of truth, and every allocation, showback and forecast inherits the price it starts from. Before these changes, a call to a model the book did not know was reported several times too high, with nothing to say so. Now a price is either the vendor's list rate, cited and dated, or it is visibly a fallback, and the export tells finance which. The reconciliation question changes from "why is this number wrong" to "which rows were estimated".
For the record: TokenFuse 1.7.0 (7 to 8 October), 1.8.0, 1.13.0 (13 October) and 1.14.0; CostCrew 0.5.0 and 0.6.0; Verdryx price-book mirrors; the cross-repository price gate.
When a call reaches the provider and no answer comes back (the process crashes, the connection is cut, the request times out), the provider may still bill it. The gateway kept that reservation in memory, so a restart forgot it. A gateway that had just started could also let calls through before it had read which budgets were already spent, and a gateway being stopped could lose its most recent records.
call_retained (medium) and a closure writes retained_closed (high). The notifier tells a person that money is waiting, with the amount in the subject, and the record keeps the closure beside the console's own log.seed_pending) until the gateway has read its control plane. This was found on 14 October, when a freshly started gateway admitted calls for a unit already over its monthly cap.In agent systems, spend leaks at the edges: timeouts, crashes, retries, restarts. Finance treats a cost that has probably been incurred but not yet invoiced as an accrual, and these changes give the gateway the same discipline. An unknown is never rounded down to zero; it stays a liability, visible to a person, until someone with authority closes it with evidence, and the record shows who did.
For the record: TokenFuse 1.5.0 (run ceiling), 1.9.0 and 1.10.0 (12 October), 1.14.0 (15 October); console money views; Heraldyx 0.4.0 and Trailryx 1.2.0 for the new events; the stack-single and stack-k8s closure secret.
The damage an agent can do arrives as a tool call: run a command, write a file, send a message, move money. With MCP, tools also describe themselves, and that description is text the model reads and follows. A poisoned description, or a tool that quietly changes after it was approved, can steer the agent. And one path, answers streamed token by token, was not judged at all.
allow_tool) and the only models (allow_models). A call whose risk signal never arrived is held for a person (when_absent: hold). A risk signal can hold a call but never deny it, and an approval is bound to the exact call a person read.A model can be persuaded; a check in the path cannot. Every item above moves a decision out of the model's judgement and into the path of the call, where it gives the same answer every time and can be tested. For a buyer this is the difference between hoping an agent behaves and knowing what stops it when it does not. Security by design explains the eight decisions this rests on.
For the record: TokenFuse 1.10.0 to 1.14.0 (12 to 15 October); Wardryx 1.2.0 (4 October), 1.3.0, 1.4.0 and 1.5.0 (13 to 14 October); stack-single 1.1.29 and 1.1.31; Mockryx and the template catalog on main.
Several settings read a value they did not recognise as "use the weaker mode". A gateway started with TOKENFUSE_FIREWALL=enfroce ran in shadow, refusing nothing, while its operator believed it was enforcing. A policy written with deny_tolls instead of deny_tool was accepted and stored without the rule, and the call it was meant to stop went through.
Misconfiguration is the most common way real systems fail, and a control that fails silently is worse than none, because people stop watching what they believe is guarded. The rule now holds across the stack: unset means the safe default, and misspelt means stop.
For the record: TokenFuse 1.5.0, 1.11.1 and 1.12.0; Wardryx 1.3.1 and 1.3.2 (13 October); CostCrew 0.4.0; stack-single and stack-k8s releases of 4 to 14 October.
An audit asks who did something. When a call was refused because its key claimed to be another agent, the refusal was filed under the agent that was claimed, so a misused key could put the blame on an innocent agent. A refused key left no trace on the event bus. And on 14 October a replaced pod kept writing after its successor took over, which broke the chain of its own record.
call_retained, retained_closed, dlp_shadow, anomaly_hinted, chain_broken and chain_unchained), and the record and the notifier learned to read them. Wardryx's policy_updated now also names the key that made each change (on main).Accountability needs two things: the record must name who actually acted, and it must show that nothing was changed or lost. These changes close both gaps. A refusal now points at the key that made the call, and the record can prove it has one writer and an unbroken chain.
For the record: TokenFuse 1.7.0, 1.8.0 and 1.14.0; Idryx 1.1.0 to 1.2.1; Heraldyx 0.3.0 to 0.6.0; agent-stack-go 1.1.0 to 1.3.0; Trailryx 1.1.0 to 1.2.1; Vouchryx 0.2.0; the agent-passport specification on main.
A cost optimisation looks like an anomaly to a detector that only sees the trend. Teams either learn to ignore the alerts after every planned change, or they stop announcing changes. CostCrew, the FinOps crew that works through the gateway, moved from 0.2.2 to 0.6.0 in this period.
This closes a loop most FinOps practices leave open. A planned saving no longer floods the anomaly queue, a saving that lands short or late is named, and the forecast and the queue agree with what the owner decided. For agent spend in particular, the data now arrives in the format finance tools already read.
For the record: CostCrew 0.3.0 (4 October), 0.4.0 and 0.5.0 (8 October), 0.6.0 (13 October), and the changes merged on 14 and 15 October; runs recorded on 7 and 8 October.
Controls only help if the people running them can trust the signals. An alert stream that pages at 3 a.m. for things that can wait gets muted, and a console that shows only successes hides the moment a gateway goes quiet.
Operators judge a system by its bad nights. These changes make the quiet nights quieter and the bad ones louder, and they make the most important signal, that something went silent, visible.
For the record: Heraldyx 0.7.0 (15 October); console image 1.1.46; stack-single 1.1.35 and stack-k8s 1.1.46.
A control nobody has fired is a guess, so on 14 October we broke the running stack deliberately: on a five-node cluster on Google Cloud, a five-node cluster on AWS, a home server, and two small routers running a third-party agent through the gateway. Every run is recorded with its date, machine and evidence. Some results, and what each one changed:
| what we did | what happened | what changed |
|---|---|---|
| Killed each of 14 services on the home server in turn | All 14 restarted in 0.38 to 0.85 s and were healthy within a second | Nothing needed; kept as a baseline |
| Reset all five servers of the Google Cloud cluster at once | Serving again in 327 s with the same state, no manual step | Nothing needed |
| Cut the policy service off from the gateway for about a minute | Calls refused from 2.5 s on, 126 of 155, each naming the closed failure mode | Confirms the failure answer is closed |
| Padded a tool call past 12 KiB | Its risk signal never arrived; the call was allowed | Wardryx 1.4.0 holds a call with no signal; re-measured on both clouds the same day |
| Streamed a tool call after a web read | It reached the agent and ran | TokenFuse 1.14.0 judges streamed tool calls |
| Started a gateway before its control plane | It admitted calls for a unit already over its cap | TokenFuse 1.14.0 waits for the money state |
| Replaced a policy pod | The old pod wrote after the new one; the on-box verifier flagged the broken chain | agent-stack-go 1.2.0 and 1.3.0: one writer per file |
| Ran the security tests on the Google Cloud cluster | Kubernetes secrets were stored in plain text | Every server is now required to start with encryption |
The TokenFuse 1.14.0 fixes were tested against stub providers, not re-measured live; the single-writer lock is pinned in Wardryx but not yet in a Wardryx release. Both are named as open in the run record. Security by design tells the same day from the side of the controls it tested.
The same changes, filed under the service that shipped them. "Shipped in" names the release; on main means merged but not yet in a tagged release. Where a service page used to carry its own list of changes, those lines are here.
| shipped in | what it does |
|---|---|
| v1.5.0 | A gateway mode the gateway cannot read stops it at start. |
| v1.5.0 | An operator can cap the budget a caller declares for a run. |
| v1.7.0 | The price book holds a row for every Claude model Anthropic lists, at its list rate, and the Gemini models on Vertex AI. Before this, a call to a model the book did not know was charged at a fallback rate several times too high. |
| v1.7.0 | A Gemini thinking call is charged the reasoning tokens Google bills, and an operator can supply prices in a file. |
| v1.7.0 | A call refused because its key claimed another agent is exported under the credential that made it, not the agent it claimed. |
| v1.8.0 | The Cloud and the dashboard file that refusal under the credential too, show a refused run as refused, and mark calls priced from the fallback. A gateway shows the book it charges with, and a call forwarded in identity warn mode is marked as such. |
| v1.9.0 | A call whose outcome is unknown is kept as money owed. The reservation survives a restart, and a person closes it with evidence, using a short-lived token that the operator console mints after a passkey check. |
| v1.9.0 | The Cloud's development key fallback is removed. |
| v1.10.0 | A retained call and its closure are written to the event bus, so a notifier can tell a person that money is waiting. |
| v1.10.0 | The MCP broker waits up to 1,000 ms for a policy decision instead of 50 ms, because a slow deny used to arrive after the broker had given up. |
| v1.11.0 | Tool metadata is scanned for five warning signs: a credential, an order to run another tool, a path to local credentials, text addressed to the model, and hidden text. |
| v1.11.0 | With the scan set to block, a tool whose definition changed after it was pinned is refused on the call. |
| v1.11.0 | Tools a request declares are read for poisoning. A poisoned description marks the run as a suspected injection. The request itself is not refused. |
| v1.11.1 | A firewall mode the gateway cannot read, such as enfroce, stops it at start instead of running a firewall that refuses nothing. |
| v1.12.0 | Text recalled from an agent's memory is untrusted context. Under the starter policy, a run that carries it cannot then run a command, write a file or reach the network. |
| v1.12.0 | The compliance catalog cites the OWASP MCP Top 10, row by row, against the test that holds each control. |
| v1.12.0 | Nine more security switches (data-loss and PII scanning, the MCP scan, the fail modes, the policy mode and two broker requirements) stop the gateway at start on a value they cannot read. |
| v1.13.0 | Prices for the current OpenAI, Gemini, DeepSeek, Kimi and GLM models are at their vendors' rates. A model sold at two rates by prompt length is priced by the tier each call falls in. A model the book cannot price exactly keeps a fallback rate, and the call says so. |
| v1.13.1 | Tool arguments up to 12 KiB reach the policy whole. Larger arguments are marked as truncated, so the policy still decides. |
| v1.14.0 | A tool call inside a streamed answer is judged like one in a buffered answer, and a denied call is cut before it reaches the agent. |
| v1.14.0 | Nothing a budget governs is admitted until the gateway has read its money state, so a restart cannot admit calls for a unit already over its cap. |
| v1.14.0 | A refused client key reaches the event bus with its reason and a fingerprint of the key, never the key itself. |
| v1.14.0 | IBANs are a kind of personal data the scanner finds, checked by country code, length and check digits, and decimal numbers are no longer mistaken for card numbers. PII that is found and let through is reported as kinds and counts, never the text. |
| v1.14.0 | Every FOCUS export row says whether it was priced from the price book or from the fallback, and ids written as openai/... are priced at OpenAI's list rate. |
| v1.14.0 | On shutdown the gateway stops taking calls, delivers what it still holds to the Cloud within five seconds, and logs how many records did not arrive. |
| shipped in | what it does |
|---|---|
| v0.3.0 | Decided thresholds for anomalies (USD 2,500) and urgent ones (USD 12,500). |
| v0.4.0 | Provider usage is read from the vendors' own usage reports and reconciled against the gateway's rows, so the gap between the two is shown. |
| v0.4.0 | Sign-in through the organisation's identity provider, over OpenID Connect with signed tokens and PKCE. Session tokens are stored hashed, every failed sign-in gets the same answer, and the console sets security headers. |
| v0.4.0 | Readers for AWS Data Exports and Google Cloud billing exports in plain FOCUS. |
| v0.4.0 | Showback per customer unit, with an allocation rule a person stamps. |
| v0.4.0 | A setting decides whether a model is sent full data, masked data or aggregates only, and a model the organisation hosts itself can run the crew. Both were run on 7 and 8 October, from a fully closed network to a cloud model. |
| v0.4.0 | A thinking model's reasoning is counted as output tokens. |
| v0.5.0 | A re-exported trace is counted once, however many times the same calls are exported, and a call refused for identity is filed under the credential that made it. |
| v0.6.0 | A cost decision the crew recommends can be announced before it lands. Only the owner can confirm it, and a day that matches the announcement is not raised as an anomaly. |
| v0.6.0 | A day that misses the announcement is raised with the decision's name. The forecast carries the step before it lands, after the month closes each decision shows announced against measured, and a saving larger than the service's median daily spend over 28 days is refused. |
| v0.6.0 | Its own price table is corrected to Anthropic's list rates: Claude Sonnet 5 at 2 / 10 instead of 3 / 15, Claude Opus 5 at 5 / 25 instead of 15 / 75. |
| on main | A FOCUS 1.1 file of agent spend, by agent, unit, model and credential, for a FinOps platform's custom ingress. No file has been accepted by a live tenant yet. |
| on main | Spend priced from a fallback is kept apart, PII let through is named, each run shows every model it used with its share, and each gateway door is shown as its own source. |
| shipped in | what it does |
|---|---|
| v1.2.0 | A typed risk signal can hold a call, never deny it, and an approval is bound to the exact tool call a person read. |
| v1.3.0 | A policy can name the only tools its agents may use. A requested tool the list does not name is denied, and no approval can lift that. |
| v1.3.1 | Every document of a YAML policy file, and every value of a JSON policy file, is loaded. A file that does not load stops the service at start, and the error names the part that failed. |
| v1.3.2 | A policy write with a field the policy does not declare is refused with a 400, and nothing is stored. Before, the field was dropped and the write still answered 200. |
| v1.4.0 | A policy can hold a tool call whose risk signal never arrives (when_absent: hold), for a person to decide. |
| v1.5.0 | A policy can name the only models its agents may use. A request for any other model is denied on that call. |
| on main | A policy change made through the API names, on the event bus, the fingerprint of the key that made it. |
| on main | The shared library's single-writer lock is pinned, so a replaced pod cannot break its own chain. Not yet in a Wardryx release. |
| shipped in | what it does |
|---|---|
| v1.1.0 | An event is ingested as the source it claims only when its file may carry that source, so one component cannot speak for another. |
| v1.2.0 | The second gateway door's file, the one that speaks the OpenAI wire format, is ingested as TokenFuse. Before, it was refused as a foreign source, so that door's agents never reached the graph. |
| v1.2.1 | Event types and sources that no detector reads are named as such, not reported as unknown. |
| shipped in | what it does |
|---|---|
| v0.2.0 | The public revocation list no longer says who revoked a token or why. |
openai/... rows.| shipped in | what it does |
|---|---|
| v0.4.0 | Ships the action.risk_class template, and a reverse proxy that adds a risk signal to a policy decision request. |
| v0.4.1 | A call whose arguments were truncated is counted as a skip, and its log line is rate-limited. Built with Go 1.27.2. |
| shipped in | what it does |
|---|---|
| v1.1.0 | A readiness path on the ingest listener answers 200 while ingest is healthy and 503 once it is degraded. A TLS library security update. |
| v1.2.0 | Reads the gateway's call_retained and retained_closed, so the record keeps a closure beside the console's own log. |
| v1.2.1 | A TLS library update for four published advisories. |
| shipped in | what it does |
|---|---|
| v0.3.0 | An event is processed as the source it claims only when its file may carry that source. |
| v0.4.0 | Describes the gateway's call_retained and retained_closed, so a person is told that money is waiting, with the amount in the subject, and the chain verifier's chain_broken and chain_unchained. |
| v0.5.0 | The second gateway door's file is read as TokenFuse. |
| v0.6.0 | A fix to how the notifier keeps its place in the event file. |
| v0.7.0 | A daily pulse mail says the notifier is running and gives the counts it saw, so a quiet box can no longer look like a dead one. |
| v0.7.0 | Quiet hours hold alerts below critical every day, in a window the operator sets and in the time zone the operator names. |
| v0.7.0 | A maintenance window, opened by hand for up to 24 hours, can hold alerts from one source while that source is being upgraded. |
| v0.7.0 | An operator can acknowledge a known condition for four hours by default, seven days at most. Its repeats are counted instead of mailed, and one mail says how many alerts were held when it ends. |
| v0.7.0 | A critical is never held, whether by quiet hours, a window or an acknowledgement. |
| shipped in | what it does |
|---|---|
| agent-stack-go v1.1.0 | An on-box chain verifier (agent-conform) with a published image of its own. |
| agent-stack-go v1.2.0 | The chained event writer locks the file and chains from the line on disk, so several writers appending to one file keep one valid chain. |
| agent-stack-go v1.3.0 | A plain event writer takes the same file lock for each append. |
| agent-passport, on main | Six event types registered (call_retained, retained_closed, dlp_shadow, anomaly_hinted, chain_broken, chain_unchained), and a reserved "unidentified caller" subject. |
| Terraform provider, on main | Still 0.2.0 as a release; fixes merged since, among them the passport resource listing dpop-key among the attestation methods. |
| service | what it does | before 1 Oct | 15 Oct | releases | PRs merged |
|---|---|---|---|---|---|
| TokenFuse | Gateway, prices and budgets, MCP broker | 1.4.1 | 1.14.0 | 14 | 97 |
| Wardryx | Policy decisions: allow, deny, hold | 1.1.3 | 1.5.0 | 6 | 31 |
| CostCrew | FinOps crew and console | 0.2.2 | 0.6.0 | 4 | 60 |
| Heraldyx | Notifier | 0.2.5 | 0.7.0 | 5 | 31 |
| Idryx | Agent identity graph and detectors | 1.0.0 | 1.2.1 | 3 | 16 |
| Trailryx | Tamper-evident record | 1.0.0 | 1.2.1 | 3 | 19 |
| agent-stack-go | Shared library, event writer, chain verifier | 1.0.2 | 1.3.0 | 3 | 16 |
| Typryx | Typed answers and risk signals | 0.3.0 | 0.4.1 | 2 | 16 |
| Vouchryx | Delegation tokens | 0.1.0 | 0.2.0 | 1 | 10 |
| Console (Genaryx) | Operator console and Felyx | image 1.1.19 | image 1.1.46 | - | 40 |
| Engram | Agent memory | 2.4.1 | 2.4.1, provenance on main | 0 | 5 |
| Mockryx | Drills | 0.2.1 | 0.2.1, four drills on main | 0 | 13 |
| Verdryx | Answer quality per dollar | - | price mirrors on main | 0 | 9 |
| Qryx, Scopyx | Crypto inventory, egress gate | 1.0.0, 1.0.1 | unchanged, docs and toolchain | 0 | 22 |
| agent-passport | Event and identity specification | 1.0.0 | six event types registered | 0 | 9 |
| Terraform provider | Infrastructure as code | 0.2.0 | 0.2.0, fixes on main | 0 | 11 |
| Template catalog | Policies and drills | - | shop guardrail and drills | 0 | 6 |
| stack-single | Launcher for one machine | 1.1.15 | 1.1.35 | 20 | 46 |
| stack-k8s | Launcher for a cluster | 1.1.21 | 1.1.46 | 25 | 55 |
| stack-up | Developer launcher | - | safer defaults on main | 0 | 12 |
Security by design explains the eight decisions behind the tool-safety and fail-closed work on this page. The glossary has the rest of the vocabulary, and the guides index has every guide.