System & Agents
4 of 4 sources answered· Last 30 days
Ops Dashboard
Deployed shape
Architecture
Two Workers: one serves the site, the other serves the MCP server, chat and fit analysis. They call each other through service bindings, without a public network hop.
How this site is deployed
Two Cloudflare Workers. Visitors and agents reach the site Worker at ryanlindsey.me, which serves the pages, posts, case studies and the résumé, prerendered with some routes rendered on demand, plus llms.txt, the markdown variants and the feeds; it hosts the chat page and the form surfaces, and runs the queue consumer that sends the notification email. It calls the MCP Worker at mcp.ryanlindsey.me over a service binding for the MCP endpoint, for chat and for form posts; the MCP Worker calls back the same way to read published documents. The MCP Worker serves the MCP endpoint statelessly, rebuilding the server for each request, alongside the streamed chat inference and the discovery routes; it holds the one Durable Object in this system, which enforces the rate limits, and it is where inference runs: through AI Gateway to Anthropic, and through Workers AI into Vectorize for retrieval. Both Workers share D1 for the audit log, tokens, transcripts and eval runs, KV for caches and flags, R2 for generated PDFs and documents, Analytics Engine for request telemetry, and a queue that carries high-intent events to the email. Analytics Engine and the queue are independent sinks; neither feeds the other.
01Visitors and agents
HTTPS
02 · Site Worker
ryanlindsey.me
Astro, prerendered with some routes rendered on demand
- pages, posts, case studies, the résumé
- llms.txt, .md variants, RSS and JSON
- chat page and the form surfaces
- queue consumer and the email send
/mcp · chat · forms
document reads
03 · MCP Worker
mcp.ryanlindsey.me
The MCP server and every call that spends inference, plus the rate limiter's Durable Object
- /mcp endpoint, stateless per request
- POST /chat, the streamed inference
- /robots.txt, /.well-known/mcp.json
- rate limits in a Durable Object
- AI Gateway → Anthropic
- Workers AI → Vectorize, for retrieval
04 · Shared by both Workers · bindings
D1
audit · tokens · transcripts · evals
KV
caches and flags
R2
generated PDFs and documents
Analytics Engine
request telemetry
Queue
high-intent events → email
Last 30 days
Live metrics
225
Public MCP tool calls
D1
0
Chat sessions
D1
0
Chat turns
D1
6
Fit reports produced
D1
6 started, 0 failed, 0 abandoned, 0 in progress
101,067
Requests that reached the Worker
Analytics Engine
79,418
Requests from agents
Analytics Engine
0 ms
Median Worker time per request
Analytics Engine
$8.53
Inference spend
AI Gateway
Covers chat, fit analysis and eval judging. Search embeddings do not go through the gateway, so they are billed but not counted here.
246
Requests through the AI Gateway
AI Gateway
0
Served from the gateway cache
AI Gateway
AI Gateway
These three figures are AI Gateway's own accounting for the same window: the cost it computed for the calls it recorded. That is closer to the invoice than an estimate from token counts, but it is not the invoice. A blank figure means the read failed, not that nothing was spent, so a blank is never shown as zero. Token counts are not published. The dollar figure is what matters to a reader, and the rest describes other people's questions.
By tool · D1
- get_contact75
- get_resume35
- list_writing34
- list_case_studies33
- resource:resume21
- resource:writing17
- search_writing6
- request_private_access2
- get_case_study1
- get_post1
By agent · Analytics Engine
- unknown43,386
- other-bot19,965
- http-client8,169
- Claude-User5,012
- first-party401
- Googlebot271
- OAI-SearchBot219
- Amazonbot217
- GPTBot200
- meta-externalagent194
- CCBot160
- Applebot158
- ClaudeBot157
- Bytespider152
- ChatGPT-User144
By route class · Analytics Engine
- agent-signal83,007
- other16,641
- content1,419
Model & cost
· Constants in this buildEvery model the site calls. Each name is read from the constant the calling code uses, so the list cannot name a model the site has stopped using. Chat answers and eval judging are set separately and currently use the same model.
- Chat answers
- anthropic/claude-sonnet-5
- Fit analysis
- anthropic/claude-opus-5
- Eval judging
- anthropic/claude-sonnet-5
- Search embeddings
- @cf/qwen/qwen3-embedding-0.6b
Evals
· Latest run per suite · D1These are automated checks that run on a schedule against the live site and its MCP server, covering grounded answers, citation integrity, and whether the private surfaces stay invisible to an unscoped caller. A graded case is a real answer checked against expectations written down in advance, and the Graded column scores those cases alone. Couldn't run counts the cases where the model call never came back, which says nothing about answer quality, because there was no answer to judge. A suite that did not run at all says so on its row rather than showing its last good result.
| Suite | Ran | Graded | Couldn't run |
|---|---|---|---|
| chat | 2026-10-25 | 4/4 | 0 |
| fit | 2026-10-25 | 2/3 | 0 |
| leak | 2026-10-25 | 8/8 | 0 |
| tier | 2026-10-31 | 1/1 | 0 |
Failures
· By surface and reason · D1Failed calls over the last 30 days, counted by the part of the site they reached, by whether a visitor or a scheduled eval run made them, and by the reason recorded for each. The fit rows count calls made through the MCP server. Runs started from the fit form are counted once, in the fit reports figure above. A failure from before reasons were recorded counts as unrecorded.
| Surface | Failed | Reasons |
|---|---|---|
| chat · scheduled | no failures | |
| fit · live | no failures | |
| fit · scheduled | 1 of 35 failed |
|
| search · live | no failures | |
| judge · scheduled | no failures | |
| public tools · live | 2 of 219 failed |
|
| public tools · scheduled | no failures | |
| private tools · live | no failures |
Status & degradation
· What happens when something failsWhen a part fails, the site says so and keeps serving what it can. These are the failures in the order a visitor would meet them.
- The budget breaker trips
- The daily inference budget breaker is tripped, so chat is paused until it resets. Everything published is still readable at /llms.txt, and the MCP endpoint still answers.
- A read this page needs fails
- The figure it feeds shows as unavailable, never as zero. A wrong zero is the one error a reader cannot spot.
- Retrieval finds nothing
- Chat says the published work does not cover the question instead of guessing. Everything published is also plain text at /llms.txt, and the MCP server answers the same questions for agents.
Rate limits
- Reading a published document over MCP60 per minute
- Semantic search over the published pages10 per minute
- A chat message30 per 5 minutes
- Chat, across all visitors, before the breaker trips500 per day
What's stored, and for how long
- Chat questions and answers30 days
- The MCP audit log1 year
- Fit runs and their reports1 year
A daily job enforces these, and the AI policy states them.
Release history
- 1.54.02026-10-11
- 1.53.12026-10-02
- 1.53.02026-10-02
- 1.52.32026-10-02
- 1.52.22026-10-01