ethosteleos.dev

A character forged by its ultimate purpose.

Work|Production

Cyris

One tool-using AI operations associate with four public voices, server-owned authority, and production access to calendar, email, assessments, and payment-gated booking.

Cyris is one AI Operations Associate living on the Pyris Consulting website.

He is not a second company, a general-purpose chatbot, or four agents hidden behind four landing pages. He is one server loop with four public voices. Each voice changes the conversation and available capabilities for the job at that door; none of them changes where authority lives.

The loop can save leads, inspect genuine calendar availability, book and manage events, send confirmation mail, create Stripe Checkout sessions, and complete two structured consulting instruments. The hard part was not giving a model those abilities. It was making them safe enough to use in public.

Cyris architecture map showing four public voices sharing one conversation loop while identity, payment, possession, booking, assessment, and persistence remain server-owned
PLATE 01 One loop, four voices · entry context selects a mode but never grants authority

One loop, four voices

Every turn reaches the same server route. The server selects a playbook, tool set, and session state from the entry context, calls the model, executes requested tools, and continues until the model returns prose rather than another action.

The four voices are deliberately different:

· Homepage intake is conversational lead capture and a no-cost twenty-minute Discovery Call.

· PayFirst intake sells a $1,500 Operations Flow Check and withholds the ninety-minute booking capability until Stripe has written the paid fact.

· Operations Audit acts as a senior consultant conducting twelve silent determinations across five operational clusters and returns one of four maturity reads.

· AI Readiness reconstructs several actual processes, scores four dimensions in deterministic code, and returns a readiness read without telling the visitor a number or prescribing software.

The two assessment voices deliver their value before asking for a call. They do not save a lead answer by answer. They commit once at the end. “Mostly” is a no in the Operations Audit; AI Readiness has no failing grade.

Those details are not prompt flavor. They are product laws.

A door label is not a lock

The browser supplies an entry-context string so Cyris knows which surface the visitor entered. That string is useful routing information and worthless authorization evidence.

An attacker can omit it, replace it, or call the shared endpoint directly. Unknown context falls to the homepage behavior. Therefore no dangerous capability can be secured by saying “this tool only appears on the paid page” unless the server independently proves the condition that makes the action safe.

This is why a review proposal to remove find and cancel from the paid tool array did not close the booking hole. The attacker could simply arrive without the paid label. Capability boundaries are enforced by what the tool itself requires, not by which prompt happened to introduce it.

Possession-proof booking

The original booking tools allowed a visitor to find an event by email and cancel a raw event identifier. In a public system, that is an insecure direct-object reference wearing conversational clothing. The model’s friendly question did not make the supplied email trustworthy.

The live system uses a signed manage token delivered in the confirmation email. Possession of that token proves authority over the booking. The route handler validates it and becomes the only writer of the verified email and event id. Cancel and reschedule do not accept a model-chosen victim.

Reschedule edits the same Calendar event in place. That sounds obvious because the alternative is now dead. It took several iterations to earn.

The earlier design created a replacement and then cancelled the original. A fix for cancel-after-rebind opened a second-cancel that deleted the new booking. An armed-flag rewrite moved the same keeper-delete bug into a pending identifier. Each patch made one path survivable and relocated the root into the next piece of state.

The class finally closed when the design collapsed to one invariant: a reschedule patches the verified event; it does not create a keeper and then ask cancellation logic to remember which object deserves to live.

The model is not the cashier

On the paid door, Cyris can create Checkout. He cannot declare settlement.

Stripe’s webhook verifies the event and writes the paid fact. Booking remains unavailable until that server-owned fact exists. A return URL, assistant claim, or tool argument cannot mint authority. Cancel records the cancellation and never automatically invents a refund policy.

The test-only bypass used during live walks was deleted at the production flip. That matters because a dark path left beside the live switch can be resurrected months later by an environment variable nobody remembers. Closed-by-deletion is stronger than “currently disabled.”

Instruments, not forms wearing prose

The first assessment design used per-answer recorder tools. Each tool wrote one response mid-conversation. When the model called one, the turn could end with an HTTP 200 and no reply, leaving the visitor staring at an empty interface.

The fix was not to tell the model to remember to speak. The recorder tools were removed. Each instrument now holds its judgments in context and calls one terminal finalize operation.

The Operations Audit makes twelve yes-or-no determinations and returns a maturity reading in prose. The AI Readiness scorer is a pure function: four dimensions scored zero to two, total zero to eight, used to notify me and never announced as a grading spectacle. Code does arithmetic; Cyris conducts the human exchange.

This preserves the reason the instruments are conversations. They can ask about an actual recent instance, follow ambiguity, and reconstruct how work really moves. A disguised form would collect cleaner-looking lies.

Persistence that cannot end the conversation

At a live expo, Pyris’s free database had been paused for weeks. Lead-save failed DNS. Cyris still booked two events and sent confirmations. Most of the conversations disappeared.

The recovery design writes to the database first, then to a local overflow file and an operator email when primary persistence fails, while still returning a usable lead identity to the loop. The agent does not receive an infrastructure failure and turn it into a customer-facing apology spiral.

That does not mean failure is hidden. It means failure is routed to the person and surface capable of repairing it rather than given to the language model as new material to improvise around.

Redaction follows the same sink-first logic. Card and Social Security number patterns are checked and masked at every persistence boundary—transcript, overflow, calendar description, lead summary, and assistant prose—because a paid conversation can prime someone to paste a number that should never survive the turn.

Where it stands

All four voices are live. Homepage intake books twenty-minute calls without a payment gate. PayFirst charges real cards before making a ninety-minute Flow Check hold available. Both assessment instruments run without a results wall and commit once. The old payment-link route, book-new-cancel-old reschedule, partner mode, per-answer recorders, and dark bypass are dead.

The current open edge is not hidden. One identity-binding choke point remains currently shut rather than proved closed, and the default request limit is too low for a planned several-hundred-recipient campaign because one genuine booking conversation can require eight to fifteen posts. The campaign remains unsent until that path is ready.

Cyris is a production agent because the architecture assumes the model will eventually be persuasive, mistaken, and asked to do the wrong thing. Safety does not depend on it declining.

Provenance

Published
2026-08-31 — generated from commit history, not maintained by hand
Revised
2026-08-31 — 1 revision. Status changes are commits, never a typed field.