All Work

Client Hospitality AI Platform

Guests can get property information, check availability and report maintenance problems through an AI assistant. It answers routine questions, guides booking requests and turns reported problems into tracked work for staff, taking over repetitive information lookup and issue recording while keeping permissions and approvals with the business.

EnterpriseML InfrastructureLive

The client’s platform handled two connected jobs: routine guest support and staff coordination. A guest could ask for Wi-Fi instructions, look for a suitable property or report a leaking shower. The assistant used the property and reservation records to answer, or created a maintenance issue with a recorded next step for the operations team.

The client needed support for both prospective and staying guests, alongside an assistant for its operations team. The system connected those conversations to the existing reservation, property and maintenance records. Staff could review what the assistant had done and investigate failed requests through a control portal.

The core delivery was one shared runtime for two audiences, with configurable skills, explicit booking and issue flows, durable run state and an operator workflow connecting traces to evaluation.

The problem: helpful language was only the first step

A guest asking for the Wi-Fi instructions needs accurate information for the correct stay. A guest reporting a leaking shower needs an issue recorded, a responsible person or escalation path, and an honest account of what happens next.

Those requests can look similar in a chat interface while requiring very different operational behavior. A polite response that promises a repair without creating the corresponding work makes the second situation worse.

The host copilot brought a different authority boundary. Staff needed access to operational information and actions that should not be exposed to a guest. The operator maintaining the assistants needed another set of controls: inspect a run, change configuration, test behavior and understand cost.

UserNeeded outcomeEvidence the product had to use
Prospective guestSuitable properties for explicit dates and occupancySearch criteria and current calendar results
Guest with an active stayRelevant property or reservation informationAuthorized stay and property context
Guest reporting an issueA recorded issue and accurate next-step statusTask, assignee, appointment and escalation outcomes
Host or operations teamA scoped operational view and appropriate actionsCurrent backend records and allowed capabilities
Operator maintaining the AIAn inspectable explanation and a controlled improvement pathConfiguration, prompt assembly, tool results, traces and evaluations

Our process: work backward from the operational result

1. Translate workflows into concrete scenarios

The requirements were organized around a starting state, a user request, allowed actions and a completion condition. That made the expected behavior specific enough to implement and evaluate.

For example, a maintenance scenario had to resolve the guest’s stay, check for an existing issue, record or update the right work and report the actual dispatch status. “Be helpful” could guide tone, but it could not express those completion conditions.

I connected these client workflows to the runtime’s boundaries: who the actor was, what context the assistant needed, which tools it could use and what evidence would justify its final response.

2. Keep the hospitality backend authoritative

The existing backend already owned reservations, listings, tasks, messaging and payments. The agent service therefore integrated through internal APIs rather than recreating those business entities inside an AI framework.

The Python service owned agent execution, configuration and agent-specific state. The domain backend remained the system of record. This gave the integration a clear division: the harness could reason about an operation and retain its reference, while the backend determined the business record’s actual state.

3. Build the shared runtime and capability catalog

We developed a common execution path for the concierge and host copilot, with different personas and authority. Prompts, skills, tools, model settings and agent definitions became configurable resources. Each turn resolved the relevant capabilities and assembled the context required to use them.

4. Move mandatory operational steps into explicit flows

Booking and issue handling needed more structure than an open-ended model plan. We put the mandatory checks and state transitions into domain-specific flows, while the model interpreted the conversation and explained the returned outcome.

5. Build the operating surface alongside the assistant

The control portal brought configuration, playgrounds, run traces, evaluation and spend together. It gave the client’s team a way to see what reached the model, investigate a failure and compare a proposed change against a baseline.

Architecture: a harness around the model loop

Architecture of the domain backend, Python runtime, model access, durable state and operator console.

The custom Python and FastAPI runtime sat between incoming conversations, model providers and the hospitality backend. PostgreSQL stored durable agent state and configuration. The Next.js portal exposed the operational controls.

Patterns from OpenClaw informed the harness and lifecycle boundary, while Hermes provided a reference for the surrounding agent components. Our implementation used request-local attempts and a typed event stream suited to a service shared across tenants.

The reason for a custom harness was the responsibility around the model: admission, routing, scoped context, tool policy, deadlines, approval state, result persistence and event recording. A successful model response was only one stage in that lifecycle.

BoundaryResponsibility
Ingress and orchestrationResolve identity, admit an event, route it and own the run lifecycle
Context and capabilitiesAssemble persona, current facts, knowledge, history and allowed tools
Model executionRun a bounded tool-calling loop through provider adapters or the gateway
Domain toolsRead or change business state through the hospitality backend
Durable state and eventsPreserve conversation continuity, execution outcomes and operational evidence
Operator portalInspect configuration, reproduce behavior, evaluate changes and track spend

One runtime, two authority models

The guest concierge and host copilot shared routing, context assembly, model execution and event recording. Their personas and allowed actions differed.

The implementation supplied account and tenant scope from trusted runtime context, stripped protected scope keys from model arguments and checked tool allowlists at execution. Guest flows also used the resolved stay set and focus. Backend account-scoped access remained the final authority on the domain record.

This prevented permission from becoming only a sentence in the prompt. The assistant could interpret a guest’s request without receiving the ability to select a different tenant or grant itself a new capability.

The runtime also included confirmation behavior and a durable approval path. An action waiting for approval was represented as a distinct outcome. Conversational confirmation and an authorized approval remained different concepts; the detailed series develops the stronger action-binding and resumption checks those workflows require.

Capabilities were composed for each turn

The capability catalog included versioned prompts, skills, tool definitions, model settings and agent configurations. A request selected relevant skills, context and tools rather than exposing every operation on every turn.

Composition deduplicated shared instructions and tool sets, while authority limited the effective capability set. Prompt assembly combined stable persona fragments with fresh property knowledge, live facts, host rules and conversation state.

The operator playground displayed the assembled input and exposed tools. That made an apparently simple question—“why did this prompt change have no effect?”—answerable. The team could inspect whether the skill was selected, the fragment was included and the tool survived policy filtering.

It also avoided creating a new autonomous agent for every intent. Booking, issue reporting and reservation questions could be capabilities of the same concierge when they shared audience, authority and conversation continuity.

Booking: preserve the conversation, recheck the facts

The booking flow separated property discovery from calendar verification. A property matching a description was a candidate; availability required a current calendar result for the requested dates and occupancy.

Conversation state preserved earlier options and their ordinals. That mattered when a guest referred to “the second one” or returned to a previous search after changing dates. The selection had to resolve against the options actually shown, with their associated context.

Before returning a checkout link, the flow rechecked availability. The response could then describe a checkout opportunity accurately. A checkout link remained distinct from a confirmed reservation, whose state belonged to the booking backend.

The division of work was deliberate: the model handled flexible language and comparison; the application owned remembered options, fresh checks and the meaning of the resulting booking state.

Maintenance: a task is not the same as a dispatched repair

Issue handling connected a guest complaint to a scoped stay, duplicate checks, staff availability, task ownership and escalation. The returned result distinguished a proposed task, an assigned person, a booked slot and notification evidence.

An illustrative request makes the difference clear: a guest says, “The shower is leaking. Can someone come this afternoon?” A useful response depends on what the operation actually returned. A task with an assignee but no appointment does not justify promising an arrival time. An escalation record does not establish that a staff notification was delivered.

The implementation’s explicit flow reduced dependence on the model remembering every mandatory step. It also made backend semantics part of the product contract: an accepted request, suggested action and completed mutation could not all be treated as the same success.

Longer operations could be handed to asynchronous workflows. Their acceptance was separate from eventual completion, so the conversation and follow-up path needed a correlated workflow identity and an accurate status.

Reliability involved identities, state and side effects

The runtime organized execution around tenant, session, run and attempt identities. A tenant defined account scope; a session grouped conversation continuity; a run represented admitted work; an attempt represented an execution envelope.

Inbound idempotency sat ahead of classification and paid model work. Durable run and conversation state supported inspection and continuity, and lifecycle outcomes distinguished completion, failure, timeout and waiting for approval. Stage timings helped separate routing and context costs from the model loop itself.

A durable outbox supported retryable projections such as backend audit delivery. This addressed a different risk from duplicate inbound messages. A retryable audit record did not, by itself, guarantee exactly-once business mutations.

Those distinctions shaped the reliability work: admitting an event once, preventing duplicate domain actions and delivering audit evidence were separate boundaries. The technical series develops crash recovery and stronger release checks around them, including the points where a backend receipt must remain authoritative.

The control portal made the system operable

Conceptual map of the implemented operator portal: configuration, playground, traces, evaluation, spend and contracts.

The Next.js portal included prompts, tools, skills, agents and models; a multi-turn playground; tool-contract and deployability views; run traces; evaluation datasets and runs; offline reports; observability; and spend.

Its value was the connected investigation path. An operator could inspect a conversation, examine route and prompt assembly, inspect tool results and identify the configuration responsible for the behavior. A persisted run could then become an evaluation case.

That brought the product’s improvement loop into the same operating surface as the assistant. A bad response did not have to remain an anecdote or an isolated log entry.

Evaluation checked behavior and business evidence

Evaluation combined deterministic assertions, configurable model judges, human verdicts and baseline comparisons. The two kinds of checks served different purposes.

A deterministic check could establish whether a tool was called, whether a returned record existed or whether a forbidden action occurred. A judge or human reviewer could assess clarity, appropriateness and whether the response accurately described the evidence.

The distinction was especially valuable for false completion. A response could sound successful while the backend contained only a proposal or an unresolved task. Evaluating the final sentence alone would miss the failure.

The platform tracked agent cost and judge cost separately. That made evaluation visible as an operating expense and helped connect quality changes with their latency and cost consequences.

My contribution

My role was architect and developer, spanning the runtime, domain integration and operator experience.

  • Workflow translation: turned hospitality requests into execution boundaries, required evidence and implementable booking and issue flows.
  • Custom harness: worked on the shared runtime, request-local execution, capability composition and lifecycle behavior for the two assistants.
  • Domain tools and state: connected conversation context to the existing backend’s reservations, properties, tasks and operational outcomes.
  • Operator controls: developed the control portal and its connection to prompt assembly, tools, traces, evaluation and spend.
  • Quality and iteration: connected observed behavior to repeatable scenarios and baseline comparisons so changes could be investigated and evaluated.

The work required moving between customer workflows, backend semantics and model behavior. The most important decisions often sat at their intersection: what the assistant could claim, which state was authoritative and how an operator could tell what happened.

Outcomes

The delivered capabilities included a shared runtime for two assistants, dynamic capability composition, explicit booking and maintenance flows, durable execution records, and a control portal connecting configuration to evaluation and cost.

Those are the concrete product outcomes. Operational savings and automation rates would need a separate, consistently defined before-and-after dataset; no such percentage is claimed here.

The broader result was an agent product with an operating model around it. Guest requests could be connected to backend evidence, and the client’s team had a way to inspect, test and change the behavior responsible for those results.

Explore the engineering in depth

Technical Stack

LayerTechnology
RuntimePython, FastAPI, Pydantic, Asyncio
StatePostgreSQL, SQLAlchemy, Alembic, Versioned configuration
ModelsProvider adapters, LiteLLM gateway, Bounded tool-calling loop
OperationsRails APIs, Booking and issue flows, Trigger.dev workflows
ControlNext.js, React, TypeScript, TanStack Query
QualityScenario evals, LLM judges, Human calibration, Runtime event traces
Go deeperEngineering agent harnesses, 18 articles

How engagements like this are scoped and delivered: How I Work.