/scryHow Scry works
Scry answers one question about a live Kubernetes service: what is actually happening to it. You cast it from Slack or a terminal as /scry followed by a service name, and an operator running inside your own cluster reads that service's container logs, Kubernetes events and pod metrics, correlates them against the most recent rollout, and posts back a single answer with the lines it relied on. It is read-only by construction: the Kubernetes service account behind it holds get, list and watch on a fixed set of resources and nothing else, so a scry cannot restart, patch, scale or delete anything, and it cannot read a Secret. You are never issued cluster credentials, and there is no shell behind the command.
Spellbook is pre-launch. This page describes how Scry works, not a product you can install today. The transcript figures are from the demo on this site and are labeled where they appear.
How it works
It runs in your cluster, not ours
Scry is not a service you send your logs to. The Spellbook operator is a Deployment you run in your own cluster, in its own namespace, alongside the workloads it reads. Your logs, events and metrics are read in-cluster and summarised in-cluster. What leaves is the answer, and it leaves to your Slack workspace or your terminal, not to us.
The operator holds an outbound connection to Slack (Socket Mode) rather than an inbound endpoint, so nothing about Spellbook needs to be reachable from the internet: no ingress, no public URL, no inbound firewall rule. The terminal client talks to the operator over your own network.
It reads three sources, and only three
A cast resolves the service name against the workloads your team is granted, then reads: the container logs of the pods behind it (the pods/log subresource, over a bounded time window with a line cap), the Kubernetes events in that namespace, and pod and container metrics from metrics.k8s.io. If you point the operator at a Prometheus you already run, it can add a read-only query to that list. It never adds a fourth source by reaching for a shell.
The grant behind Scry is get, list and watch on pods, pods/log, events, deployments and replicasets, in the namespaces your team owns. There is no verb in it that changes anything, and core/v1 Secrets are not in it at all. This is enforced by Kubernetes RBAC, not by our good manners: an API call outside that grant is rejected by the API server, not by our code.
It correlates, then it cites
The answer is built by anchoring on the first anomaly in the window (an error rate, a probe failure, a spike in restarts), then lining that timestamp up against the ReplicaSet that owns the current pods. That is where a sentence like "started four minutes after revision v482" comes from: the ReplicaSet's creation timestamp is a fact in the API, not a guess.
Repeated log lines are grouped rather than dumped, and the answer quotes the specific lines it relied on so you can check its work. If the sources do not support a cause, Scry says it cannot explain the failure and lists what it looked at. It does not fill the gap with a plausible story.
It redacts before it speaks
Slack is outside your cluster, so anything Scry quotes crosses a boundary. Log lines are matched against secret-shaped patterns (bearer tokens, connection strings with credentials, private keys, cloud access keys) and redacted before the answer is posted, and the number of redactions is recorded in the audit record. The operator will refuse to quote a line it cannot redact confidently rather than post it.
It knows who is asking
Identity comes from the surface you cast on: your Slack identity, or your SSO identity in the terminal. The operator maps that to the spells you have been granted and mints a token for the single cast, valid for minutes. Nobody holds a long-lived credential, so there is nothing to leak from a laptop and nothing to rotate after someone leaves.
An AI agent is enrolled the same way: it gets its own identity and its own grants, and it can be given /scry without being given anything else. An agent that can read a service's logs and nothing else cannot delete that service, because the permission to do so was never issued to it.
Setting it up
Setup is done once, by whoever already administers the cluster, and it is the only moment cluster access appears anywhere in this story. Everybody who casts a spell afterwards holds none. The steps below are how the design works; nothing here installs today.
Install the operator, once per cluster
It runs in its own namespace, alongside the workloads it will read. Nothing is exposed: the chart creates no Service, no Ingress and no public endpoint, because the operator dials out rather than being called in.
shellhelm repo add spellbook https://charts.spellbook.dev helm install spellbook spellbook/operator \ --namespace spellbook --create-namespaceSay what your team owns
The ownership map is the thing that makes "checkout" resolve to one workload and not another. Keep it in the repo, next to the code it describes, and review a change to it the way you would review a change to a deploy pipeline.
spellbook.yamlteams: - name: storefront members: - ana@northwind.example - sam@northwind.example owns: - deployments.apps/checkout-api in storefront - deployments.apps/cart-api in storefrontGrant the spell
A grant is a spell, given to a team, over what that team owns. The operator reconciles it into an ordinary Kubernetes Role, so the limit is enforced by your API server rather than by our good intentions, and you can read it with the tools you already have.
spellbook.yamlgrants: - team: storefront spells: [scry] # becomes, in namespace storefront: # rules: # - apiGroups: ["", "apps"] # resources: [pods, pods/log, events, deployments, replicasets] # verbs: [get, list, watch] # # There is no fourth verb, and Secrets are not in the list.Connect Slack, outbound
Socket Mode holds a connection from your cluster out to Slack, so Slack never calls you. There is no callback URL to expose, no inbound firewall rule to open, and nothing about Spellbook that a stranger on the internet can reach.
shellkubectl create secret generic spellbook-slack \ --namespace spellbook \ --from-literal=app-token=xapp-… \ --from-literal=bot-token=xoxb-…Cast it
Ana is in the storefront team, and the storefront team was granted Scry over checkout-api. She types this in the channel she was already in. She has no kubeconfig, and she never gets one.
slack/scry checkout
This is the design, not an install guide: the chart, the file format and the flags do not exist yet. It is written out this far because a mechanism you can argue with is worth more than a promise you cannot.
What it never receives
The list a security review asks for, on the page rather than in a PDF behind a form.
- No kubeconfig and no cluster credential. The operator's service account never leaves the cluster, and you are never issued one.
- No shell. Scry's grant contains no exec, attach, port-forward or ephemeral-container permission, so there is no path from a cast to a prompt inside a pod.
- No Secrets. core/v1 Secrets are excluded from the grant, so a scry cannot read one even when the answer would be easier if it could.
- No long-lived token. You authenticate as yourself; the token behind a single cast expires in minutes.
- No cloud credentials. Nothing in Spellbook holds an IAM role, a cloud access key, or a CI token.
- No copy of your data. Logs and metrics are read and summarised in your cluster. Spellbook keeps no store of them, because there is no Spellbook-hosted service for them to be sent to.
What it refuses to do
A permission that was never issued cannot be misused, by a person, by a compromised account, or by an agent.
- kubectl logs -f checkout-api
- You do not have kubectl. Not revoked: never issued. The spell is the interface, so the dangerous version of this action does not exist for you to get wrong.
- /scry billing-api
- A workload in a namespace nobody granted you. Refused before any Kubernetes API call is made, and refused again by RBAC if that check were ever wrong. The reply names the team that owns it and how to ask them.
- Read a Secret, or an environment variable holding one
- Not in the grant. If a credential appears in a log line, it is redacted before the answer leaves the cluster, and a line that cannot be redacted confidently is not quoted at all.
- Fix what it just found
- Scry holds no write verb of any kind. It cannot restart, patch, scale or delete. The answer ends at the answer, and restarting is a different spell with a different grant.
- Hold a session open
- A cast is bounded. It reads a window, returns one answer, and closes. There is no live session to leave running, and nothing to forget to close.
- Guess
- If logs, events and metrics do not support a cause, Scry says so and lists what it checked. An invented cause is worse than no answer, because you would act on it.
The audit record
A cast is not an action taken quietly on your behalf. Every one of them leaves a record naming the person, the grant, the exact API calls made, and what came back.
cast cst_4a7d21c0
spell /scry checkout
actor ana@northwind.example (slack:U03QK4T2P · sso:okta|00u1a4h2)
surface slack #checkout-oncall
at 2026-07-13T14:31:52Z
grant scry → pods, pods/log, events, deployments, replicasets
[get, list, watch] in ns storefront
target deployments.apps/checkout-api ns storefront uid 9c2a8f1e
read pods/log ×3 window 14:20–14:32Z, 1,412 lines
events ×27 metrics.k8s.io/pods ×3
wrote nothing
result ok · answer posted · 812ms · 0 redactions
also event SpellCast on checkout-api · slack thread permalinkWhere a record lands
- The operator's stdout, as structured JSON, so whatever log pipeline you already run picks it up with no new integration.
- A Kubernetes Event on the target workload, so kubectl describe deployment checkout-api shows the cast and the human who asked for it.
- The Slack thread itself, which is the version a person can actually read six weeks later.
- Your API server's own audit log records the operator's calls independently. The cast id is annotated on them, so the two accounts can be joined and compared.
Failure modes
What happens when it cannot do the thing.
- The pod is already gone
- Scry reads the previous container's logs where the kubelet still holds them. When they are gone, it says the logs are gone rather than answering from what is left.
- You do not run metrics-server
- The answer is built from logs and events alone and is marked partial, with the source that was missing named. It does not silently drop a leg and present the result as complete.
- The window is enormous
- The read is capped by time and by line count. Scry reports how much it read, so a thin answer is visibly a thin answer rather than a confident one.
- Nothing explains it
- It says so, lists what it checked, and stops. The next move is yours, and you have not been told a story.
- The operator cannot reach the API server
- The cast fails loudly with the API error, and the failure is recorded like any other cast. A spell that quietly returns nothing is worse than a spell that says it is broken.
Questions
How do I debug a Kubernetes service without kubectl access?
Cast /scry followed by the service name, from Slack or your terminal. A Spellbook operator running inside your cluster reads the service's container logs, Kubernetes events and pod metrics with a read-only service account, correlates them against the most recent rollout, and posts back a single answer with the lines it relied on. You never hold a kubeconfig, a cluster credential, or a shell, because the read is performed by the operator under a grant that contains only get, list and watch.
Can I read pod logs without cluster credentials?
Yes. The credential lives with the operator in your cluster, not with you. You authenticate as yourself through Slack or SSO, the operator checks that /scry has been granted to you for that service, and it reads the logs on your behalf under its own read-only service account. Nothing is issued to your laptop, so there is nothing on your laptop to steal.
What permissions does Scry actually need?
Get, list and watch on pods, the pods/log subresource, events, deployments and replicasets, limited to the namespaces your team owns, plus read access to metrics.k8s.io. It holds no write verb of any kind and no access to core/v1 Secrets. Every one of those limits is enforced by Kubernetes RBAC, so a bug in Spellbook cannot exceed them.
Does Scry send my logs to a third party?
No. The operator runs in your own cluster and reads and summarises in place. There is no Spellbook-hosted service in the path and no store of your data on our side. The answer is posted to your Slack workspace or your terminal, and quoted log lines are matched against secret-shaped patterns and redacted before they cross that boundary.
Can an AI agent use Scry?
Yes, and it is enrolled the same way a person is: its own identity, its own grants. An agent can be given /scry and nothing else, which means it can read a service's logs and cannot restart, patch or delete that service, because the permission to do so was never issued to it.
What does Scry do if it cannot find the cause?
It says it cannot explain the failure, lists the sources it checked and the window it read, and stops. It does not produce a plausible cause it cannot support, because you would act on that cause, and acting on a wrong diagnosis in production is the failure this is meant to prevent.
The machine-readable version of this page is at /spells/scry.md. It is generated from the same source, so it says the same thing.
Run this in your own cluster.
Spellbook is not open yet. Leave an address and we will come to you first.