Anaphora 0.16 is the largest release since the database move. It adds control over AI spend, an API that AI agents can use, private report links and a safe upgrade script. It also hardens every path where one user's data could reach another user. Read "Before you upgrade" at the end before you install it.
AI actions
Each AI provider now shows the tokens it used in the last 24 hours and in the last 7 days, and you can give each window a budget. When a budget is reached, Anaphora pauses the job that made the call and refuses further calls on that provider until the window rolls over. The Jobs list marks the jobs that a budget paused, and one button starts those jobs again (only those). The operator can also get an alert when a budget is reached, or earlier, at a percentage you choose.
You can now choose what each AI action reads. The "Context" section has two modes: "Everything so far" keeps the old behaviour, and "Only ticked rows" sends only the snapshots and variables you pick. You can also send snapshots as images to a model that reads them, and cap the length of the answer.
Dashboards cost less to send. On a 12-tile dashboard, the request to the model is 45% smaller and carries all twelve tiles. Before, it carried eight, because tiles with the same title were merged and Chrome's internal data took 40% of the page structure.
Reports
Report links are private. Each run gets a secret token, and the links in an email, a Slack message or a webhook carry it. A report opens only for that link or for a signed-in member of the space.
Reports cannot reach your internal network. A report is HTML and its text blocks can name any address, so the PDF renderer now refuses internal addresses: cloud metadata, localhost and private ranges. If a report shows a logo from an intranet server, add that host to REPORT_ALLOWED_HOSTS. Captures are not affected and can still open your internal Kibana or Grafana.
A broken template is not sent. A typo in a Liquid block no longer closes the job editor, but you cannot save until you fix it. If a block fails to render at run time, Anaphora withholds the report, keeps it on the run so you can see where it breaks, and flags it on the Jobs list and in job health.
Delivery status and retries
A delivery that a mail server, Slack or a webhook refused now shows as Delivery issue on the Jobs list and turns job health yellow or red. Before, it showed Success.
A webhook that answers with an error fails the delivery.
A report that reached nobody is retried. A report that reached some of its recipients is not retried, so nobody gets it twice.
Retries show under the first failed run, and the "Attempts" column counts them.
Long captures keep their retries. A capture that hangs stops after 30 minutes. A failure after the capture (full disk, PDF timeout) is a failed run, not a missing run.
Capture fixes
Grafana 12 and 13 dashboards are captured again, with all panels.
Kibana hit counts over 999 are read whole. Before, "1,470,592" was read as 1, so an alert with a threshold above 999 compared the wrong value.
The "Use regex" switch on a text replacement works. Replacements you saved before work as they did.
A ROR space or a Grafana dashboard with "login" in its name no longer fails every run.
A calculate that gives true or false no longer breaks the Runs page of its space.
For AI agents: /llms.txt and a JSON API
Every page links to /llms.txt, a guide for AI agents that work in your browser, such as Claude in Chrome. It covers jobs, captures, templates and delivery, and it describes a JSON API under /api/spaces/{space}/…. The API uses your signed-in session and the same access and licence checks as the pages, so an agent can set up a job for you without clicking through the editor.
Operations
The image includes an upgrade script. check starts the new version on a copy of your database, with no network and no deliveries, and reports what it finds. apply makes a backup, switches to the new version, checks it, and restores the backup if the new version does not start. Anaphora also copies the database before each migration.
You can set OpenID Connect sign-in (OIDC_*, Enterprise) and an AI provider (AI_*) from environment variables. The OIDC client secret stays in memory and is never written to the database.
Dark mode, in one navy hue.
The Jobs, Templates, Delivery Interfaces and AI Providers lists have one action bar for search, filters, pagination and bulk actions.
Node 24 LTS. The runtime image is about 210 MB smaller, and the build is reproducible: the same commit gives the same image.
Security
This release fixes the findings of a full security review. The main ones:
Sign-in attempts are limited per user name and per address.
A read-only member no longer receives the login passwords of a job's capture.
Report templates can no longer read server files. Templates and equations run in a separate process with a memory cap and a time limit, so they cannot stall or crash the server.
Each space is isolated. A job cannot deliver through another space's interface, a copy cannot overwrite another space's row, and a removed member loses access at once.
The server checks the edition limits, not only the browser.
The capture extension talks only to the Anaphora addresses you trust.
Sign-in secrets (OIDC, LDAP, SAML) are encrypted with your database key.
The container no longer includes sudo and runs unprivileged.
Before you upgrade
Use the upgrade script, and read "Upgrading Anaphora". This release changes the database, and the previous version does not start on the upgraded one.
Behind a reverse proxy, set AF_TRUSTED_PROXIES to the proxy's address. If you do not, all browsers share the proxy's address for the sign-in limit.
Reinstall the capture extension from the job editor, then click "Trust this Anaphora and reload" in its popup.
For intranet images in reports, add their hosts to REPORT_ALLOWED_HOSTS.
Without credentials, /guest/api/health now returns colours and counts only. For the full listing, send the system credentials with basic auth.
Form-encoded webhooks now receive the message encoded once. If your receiver decodes it twice to work around the old bug, remove that step.
Old logs can contain job passwords in clear text. Delete those logs, or change those passwords.
All users must sign in again after the upgrade.
The full list of changes, with each migration, is in the changelog.