Skip to content

feat: Add zaid-booking-agent kit — multi-agent local service booking system#207

Open
Zaid06Khan wants to merge 20 commits into
Lamatic:mainfrom
Zaid06Khan:feat/zaid-booking-agent-kit
Open

feat: Add zaid-booking-agent kit — multi-agent local service booking system#207
Zaid06Khan wants to merge 20 commits into
Lamatic:mainfrom
Zaid06Khan:feat/zaid-booking-agent-kit

Conversation

@Zaid06Khan

@Zaid06Khan Zaid06Khan commented Jul 10, 2026

Copy link
Copy Markdown

Summary

Adds kits/zaid-booking-agent/ — a multi-agent appointment booking system for local service
businesses (salon, barbershop, and similar). A customer sends a free-text booking request, and
three orchestrated Lamatic flows carry it through extraction, availability checking, and
confirmation, with a Next.js chat demo app driving the conversation.

Architecture

Four discrete flows, each with a typed input/output contract and independently testable in
Lamatic Studio — not one large prompt:

  1. Intake Agent — extracts a structured booking request (service, date, window, name,
    phone, notes) from a raw customer message; asks a clarifying question if anything required
    is missing.
  2. Scheduling Agent — checks the requested date against availability and either confirms
    the slot or has an LLM propose 2–3 real alternatives (never fabricated).
  3. Confirmation Agent — re-checks the slot immediately before "booking" (guards against a
    double-booking race), then generates a natural-language confirmation — or a decline message
    if the slot was taken in the meantime.
  4. Follow-up Agent (stretch goal, not built) — a documented but unimplemented daily
    reminder flow; scoped out to keep the initial submission focused on a fully working
    3-agent MVP rather than a partially-working 4-agent one.

Intake, Scheduling, and Confirmation are all built, tested end-to-end in Lamatic Studio (every
branch of every flow verified with real inputs), exported into flows/*.ts, deployed, and
verified against the live Lamatic API through the Next.js app's actual chat UI.

See agent.md
for the full per-flow contracts, guardrails, and failure modes, and
docs/decision-log.md
for the reasoning behind every non-obvious architectural choice (why the Next.js app owns
session state instead of flow-to-flow chaining, why availability data lives inline in a
codeNode, how branch outputs merge in the API Response mapping, etc.).

Test plan

  • Each flow built and tested node-by-node in Lamatic Studio
  • Every conditional branch in every flow verified with real matching/non-matching inputs
  • All three flows exported via Studio's "Export as AgentKit" menu into flows/*.ts
  • flows/*.ts and model-configs/*.ts type-check cleanly (tsc --noEmit)
  • apps/ builds cleanly (npm run build) and boots (npm run dev)
  • Full booking conversation (Intake → Scheduling → Confirmation) run live end-to-end
    through the deployed flows via the chat UI, including the API key rotated afterward
  • No secrets, .env files, or real credentials committed (apps/.env is gitignored;
    verified against the full branch diff)

🤖 Generated with Claude Code

  • Added kits/zaid-booking-agent/
    • kits/zaid-booking-agent/.env.example
    • kits/zaid-booking-agent/.gitignore
    • kits/zaid-booking-agent/README.md
    • kits/zaid-booking-agent/agent.md
    • kits/zaid-booking-agent/lamatic.config.ts
    • kits/zaid-booking-agent/constitutions/default.md
    • kits/zaid-booking-agent/docs/decision-log.md
    • kits/zaid-booking-agent/docs/followup-agent-spec.md
    • Flow exports
      • kits/zaid-booking-agent/flows/intake-agent.ts
      • kits/zaid-booking-agent/flows/scheduling-agent.ts
      • kits/zaid-booking-agent/flows/confirmation-agent.ts
    • Model configs
      • kits/zaid-booking-agent/model-configs/intake-agent_instructor-llmnode-254_generative-model-name.ts
      • kits/zaid-booking-agent/model-configs/scheduling-agent_llmnode-969_generative-model-name.ts
      • kits/zaid-booking-agent/model-configs/confirmation-agent_llmnode-440_generative-model-name.ts
    • Prompts
      • kits/zaid-booking-agent/prompts/intake-agent_instructor-llmnode-254_system_0.md
      • kits/zaid-booking-agent/prompts/intake-agent_instructor-llmnode-254_user_1.md
      • kits/zaid-booking-agent/prompts/scheduling-agent_llmnode-969_system_0.md
      • kits/zaid-booking-agent/prompts/scheduling-agent_llmnode-969_user_1.md
      • kits/zaid-booking-agent/prompts/confirmation-agent_llmnode-440_system_0.md
      • kits/zaid-booking-agent/prompts/confirmation-agent_llmnode-440_user_1.md
      • kits/zaid-booking-agent/prompts/followup-agent_reminder_system.md
    • Scripts (flow code nodes + availability mock)
      • kits/zaid-booking-agent/scripts/mock-availability.js
      • kits/zaid-booking-agent/scripts/intake-agent_code-node-969_code.ts
      • kits/zaid-booking-agent/scripts/intake-agent_code-node-677_code.ts
      • kits/zaid-booking-agent/scripts/scheduling-agent_code-node-970_code.ts
      • kits/zaid-booking-agent/scripts/scheduling-agent_code-node-594_code.ts
      • kits/zaid-booking-agent/scripts/confirmation-agent_code-node-672_code.ts
      • kits/zaid-booking-agent/scripts/confirmation-agent_code-node-676_code.ts
  • Added kits/zaid-booking-agent/apps/ (Next.js chat demo + API orchestration)
    • kits/zaid-booking-agent/apps/.env.example
    • kits/zaid-booking-agent/apps/.gitignore
    • kits/zaid-booking-agent/apps/eslint.config.mjs
    • kits/zaid-booking-agent/apps/next.config.ts
    • kits/zaid-booking-agent/apps/package.json
    • kits/zaid-booking-agent/apps/postcss.config.mjs
    • kits/zaid-booking-agent/apps/tsconfig.json
    • kits/zaid-booking-agent/apps/app/globals.css
    • kits/zaid-booking-agent/apps/app/layout.tsx
    • kits/zaid-booking-agent/apps/app/page.tsx
    • kits/zaid-booking-agent/apps/app/api/intake/route.ts
    • kits/zaid-booking-agent/apps/app/api/scheduling/route.ts
    • kits/zaid-booking-agent/apps/app/api/confirmation/route.ts
    • kits/zaid-booking-agent/apps/app/api/session/[id]/route.ts
    • kits/zaid-booking-agent/apps/lib/lamatic-client.ts
    • kits/zaid-booking-agent/apps/lib/session-store.ts
  • (Also present from the prior file-adds list) kits/zaid-booking-agent/apps/app/favicon.ico and kits/zaid-booking-agent/apps/public/*.svg

flow.json check

  • No flow.json file exists in the repository; flow structure is determined from the exported Lamatic modules in kits/zaid-booking-agent/flows/*.ts.

Flow node types introduced (from exported flow modules)

  • triggerNode (GraphQL API request)
  • InstructorLLMNode (Intake extraction, schema-based structured extraction)
  • LLMNode (Scheduling alternatives + Confirmation copy)
  • codeNode (represented as dynamicNode in exports; e.g., prepare clarification/success, compute availability, validate “booking”)
  • Condition (branching)
  • responseNode (maps node outputs into the flow response payload)

High-level flow behavior (what each flow does)

  • Intake Agent (intake-agent.ts)
    • Input: { message, session_id }
    • Uses InstructorLLMNode to extract a booking request (service_type required; other fields empty-string if missing)
    • Condition: if service_type is empty → returns needs_clarification: true + a fixed clarifying question; otherwise → returns needs_clarification: false + a structured request
  • Scheduling Agent (scheduling-agent.ts)
    • Input: { preferred_date, preferred_window, session_id } (window passed through; availability currently matches by date)
    • codeNode checks availability against mock OPEN_SLOTS, producing:
      • slot_available, open_slots (same-day matches), and nearby_slots (closest fallbacks)
    • Condition: if slot available → returns proposed_slots (= open_slots) and a confirmation message; else → LLMNode generates a short alternative-suggestion message using nearby_slots
  • Confirmation Agent (confirmation-agent.ts)
    • Input: { confirmed_date, confirmed_time, service_type, customer_name, session_id }
    • codeNode re-checks the selected slot against mock availability and sets booked: boolean
    • Condition: if booked → LLMNode generates a warm confirmation message; else → returns a fixed decline/failure message indicating the slot was taken
  • Follow-up Agent
    • Documented only as a stretch goal (spec + reminder prompt), not wired into the working 3-agent pipeline.

How it works end-to-end in the demo

  • The Next.js app owns per-session state, then orchestrates Lamatic flow calls in order: intake → scheduling → confirmation, displaying proposed slot buttons and re-running scheduling if confirmation fails.

…p stubs

Sets up the repo structure for the 4-agent local service booking system
(Intake -> Scheduling -> Confirmation -> Follow-up) before any flow logic
is built. Flow files are documented stubs awaiting export from Lamatic
Studio; docs, prompts, mock availability data, and the Next.js app shell
are real content since they don't depend on Studio.
…havior

The extraction schema has no nullable type, so the prompt now asks for
empty strings instead of null (the model was improvising sentinel text
like "<UNKNOWN>" otherwise). Also documents how the API Response node
merges the two Condition branches by referencing one source node per
field, relying on unexecuted nodes resolving to falsy rather than erroring.
…e merge, codeNode chip fix

Syncs local docs/prompts/scripts with the Scheduling Agent flow now built and tested
end-to-end in Lamatic Studio (both available/unavailable branches verified).
…ne path

Syncs local docs/prompts with the Confirmation Agent flow now built and tested
end-to-end in Lamatic Studio (both booked/decline branches verified). Completes
the 3-agent MVP: Intake, Scheduling, and Confirmation are all built and tested.
…PI routes

Wires up the 3-flow pipeline end-to-end at the app layer: lazy-init Lamatic SDK
client, in-memory session store, intake/scheduling/confirmation route handlers,
and a working chat UI. Verified via npm run build and a live browser smoke test
(error handling correctly surfaces when flow IDs aren't configured yet).
Replaces the doc-only flow stubs with the real, verified node graphs exported
via Studio's "Export as AgentKit" menu (Intake, Scheduling, Confirmation).
Adds a new model-configs/ directory and adopts Studio's canonical filenames
for prompts/ and scripts/, removing the earlier hand-named guesses that
predated any real export. All three flow files type-check cleanly.
Confirmed via .github/workflows/update-registry.yml, recent merged kit PR
history (e.g. Lamatic#179), and CONTRIBUTING.md's own description of the file.
@github-actions

Copy link
Copy Markdown
Contributor

:robot_face: AgentKit Structural Validation

New Contributions Detected

  • Kit: kits/zaid-booking-agent

Check Results

Check Status
No edits to existing kits ✅ Pass
Required root files present ✅ Pass
Flow .ts files present ✅ Pass
lamatic.config.ts valid ✅ Pass
No changes outside kits/ ✅ Pass

🎉 All checks passed! This contribution follows the AgentKit structure.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a Local Service Booking Agent kit with three Lamatic MVP flows, an optional follow-up specification, a Next.js chat application, in-memory session orchestration, environment configuration, prompts, scripts, and setup documentation.

Changes

Booking kit contracts and setup

Layer / File(s) Summary
Kit contracts and setup
kits/zaid-booking-agent/.env.example, README.md, agent.md, constitutions/*, docs/*, lamatic.config.ts, prompts/followup-agent_reminder_system.md
Defines kit metadata, environment variables, guardrails, architecture, flow lifecycle, setup instructions, decision records, and the optional follow-up reminder specification.

Lamatic flow implementation

Layer / File(s) Summary
Lamatic flow graphs and assets
flows/*, model-configs/*, prompts/*, scripts/*
Defines Intake, Scheduling, and Confirmation graphs, model and prompt references, clarification and availability branches, booking validation, confirmation handling, and mock slot helpers.

Application foundation

Layer / File(s) Summary
Application foundation and state
apps/package.json, apps/tsconfig.json, apps/app/*, apps/lib/*, apps/*config*, apps/.env.example, apps/.gitignore
Creates the Next.js application foundation, styling and tooling configuration, Lamatic client, and expiring in-memory session model.

API orchestration

Layer / File(s) Summary
Booking API orchestration
apps/app/api/*
Adds intake, scheduling, confirmation, and session endpoints that validate inputs, invoke Lamatic flows, update session state, and return JSON responses.

Booking chat interface

Layer / File(s) Summary
Booking chat interface
apps/app/page.tsx
Adds the client-side chat flow, intake submission, proposed-slot selection, confirmation handling, error state, and retry behavior for unavailable slots.

Suggested reviewers: amanintech, d-pamneja

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding the zaid-booking-agent kit for a multi-agent booking system.
Description check ✅ Passed The description covers the kit summary, architecture, test plan, and documentation references; only the repository checklist template formatting is missing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kits/zaid-booking-agent/agent.md`:
- Around line 104-106: The booking flow description incorrectly claims that the
`Write Booking` re-check prevents double booking. Either implement an atomic
shared reservation or conditional write for `Write Booking`, or revise the
documentation to state that the MVP does not support cross-session exclusivity
and the re-check cannot prevent concurrent bookings.

In `@kits/zaid-booking-agent/apps/app/page.tsx`:
- Around line 32-44: Update runScheduling so phase is set to
"awaiting_confirmation" only when data.proposed_slots contains at least one
slot; when no slots are returned, set phase to "intake" after preserving the
assistant message, allowing the user to submit a new request. Ensure this
behavior also applies when retrying after a failed confirmation.

In `@kits/zaid-booking-agent/apps/lib/lamatic-client.ts`:
- Around line 5-18: The getClient function does not validate the required
LAMATIC_PROJECT_ID environment variable. Include projectId in the
missing-credentials guard before constructing Lamatic, and update the error
message to clearly mention all three required variables.

In `@kits/zaid-booking-agent/apps/lib/session-store.ts`:
- Around line 1-58: Add bounded session retention to the module-level sessions
store: track each session’s last access or update time, expire stale entries via
a TTL sweep, and enforce a maximum entry count by evicting the oldest sessions.
Update getSession, getOrCreateSession, and updateSession so reads and writes
refresh retention metadata while preserving the existing Session API.

In `@kits/zaid-booking-agent/apps/package.json`:
- Around line 11-25: Add react-hook-form, zod, and lucide-react to the app
dependencies, then update the intake form and booking controls to use
react-hook-form with a zodResolver-backed Zod schema and lucide-react icons.

In `@kits/zaid-booking-agent/docs/decision-log.md`:
- Line 6: Normalize all decision headings in the decision log by changing each
heading beneath “# Decision Log” to level-two “##” headings, including the
entries identified in the review, and insert a blank line after every heading.

In `@kits/zaid-booking-agent/flows/followup-agent.ts`:
- Around line 1-29: The follow-up specification is an invalid flow stub because
it exports no flow metadata or graph structure. Move the documentation from the
`followup-agent.ts` flow file into `docs/`, or replace it with a valid flow
export containing the required metadata, inputs, references, nodes, and edges so
flow discovery can process it correctly.

In `@kits/zaid-booking-agent/lamatic.config.ts`:
- Around line 2-4: The public description in the lamatic configuration currently
claims four implemented agents. Update the description value in the
configuration metadata to describe the implemented three-agent MVP and
explicitly identify the follow-up agent as an optional, unimplemented
specification.

In `@kits/zaid-booking-agent/README.md`:
- Line 22: The README setup guide has Markdown lint issues around its fenced
code blocks. Add an appropriate language identifier to the repository-layout
fence, and ensure blank lines surround the Bash fence at the referenced
sections.

In `@kits/zaid-booking-agent/scripts/mock-availability.js`:
- Around line 45-47: Update getNearbySlots to select OPEN_SLOTS based on the
requested date and return the nearest available alternatives, passing the
requested date from its callers; alternatively, explicitly document and expose
that this fixture helper only returns the first entries so callers do not imply
date-aware behavior.
- Around line 7-9: The swap note is attached to unused mock code while the live
scheduling flow filters OPEN_SLOTS inline in
scheduling-agent_code-node-970_code.ts. Update the note to identify that code
node as the replacement point, or refactor the node to call getAvailability() so
replacing that function with a calendar provider updates the live flow.

In `@kits/zaid-booking-agent/scripts/scheduling-agent_code-node-970_code.ts`:
- Line 15: The nearby slot selection currently takes the first three entries
rather than choosing alternatives closest to the requested date. Update the
logic around `output.nearby_slots` and `OPEN_SLOTS` to parse `requestedDate`,
rank available slots by absolute date distance (with a deterministic
tie-breaker), and return the three nearest slots while preserving the expected
slot structure.
- Around line 11-14: Update the scheduling logic using requestedDate and
preferred_window so OPEN_SLOTS are filtered by both matching date and a
normalized time-window value; normalize the request and each slot’s window
consistently before comparison, then derive output.slot_available and
output.open_slots from that combined filter rather than all same-day slots.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: cd79da26-a221-432a-a0fe-e33b932d4e9e

📥 Commits

Reviewing files that changed from the base of the PR and between dafde4c and ad8ffc1.

⛔ Files ignored due to path filters (7)
  • kits/zaid-booking-agent/apps/app/favicon.ico is excluded by !**/*.ico
  • kits/zaid-booking-agent/apps/package-lock.json is excluded by !**/package-lock.json
  • kits/zaid-booking-agent/apps/public/file.svg is excluded by !**/*.svg
  • kits/zaid-booking-agent/apps/public/globe.svg is excluded by !**/*.svg
  • kits/zaid-booking-agent/apps/public/next.svg is excluded by !**/*.svg
  • kits/zaid-booking-agent/apps/public/vercel.svg is excluded by !**/*.svg
  • kits/zaid-booking-agent/apps/public/window.svg is excluded by !**/*.svg
📒 Files selected for processing (44)
  • kits/zaid-booking-agent/.env.example
  • kits/zaid-booking-agent/.gitignore
  • kits/zaid-booking-agent/README.md
  • kits/zaid-booking-agent/agent.md
  • kits/zaid-booking-agent/apps/.env.example
  • kits/zaid-booking-agent/apps/.gitignore
  • kits/zaid-booking-agent/apps/app/api/confirmation/route.ts
  • kits/zaid-booking-agent/apps/app/api/intake/route.ts
  • kits/zaid-booking-agent/apps/app/api/scheduling/route.ts
  • kits/zaid-booking-agent/apps/app/api/session/[id]/route.ts
  • kits/zaid-booking-agent/apps/app/globals.css
  • kits/zaid-booking-agent/apps/app/layout.tsx
  • kits/zaid-booking-agent/apps/app/page.tsx
  • kits/zaid-booking-agent/apps/eslint.config.mjs
  • kits/zaid-booking-agent/apps/lib/lamatic-client.ts
  • kits/zaid-booking-agent/apps/lib/session-store.ts
  • kits/zaid-booking-agent/apps/next.config.ts
  • kits/zaid-booking-agent/apps/package.json
  • kits/zaid-booking-agent/apps/postcss.config.mjs
  • kits/zaid-booking-agent/apps/tsconfig.json
  • kits/zaid-booking-agent/constitutions/default.md
  • kits/zaid-booking-agent/docs/decision-log.md
  • kits/zaid-booking-agent/flows/confirmation-agent.ts
  • kits/zaid-booking-agent/flows/followup-agent.ts
  • kits/zaid-booking-agent/flows/intake-agent.ts
  • kits/zaid-booking-agent/flows/scheduling-agent.ts
  • kits/zaid-booking-agent/lamatic.config.ts
  • kits/zaid-booking-agent/model-configs/confirmation-agent_llmnode-440_generative-model-name.ts
  • kits/zaid-booking-agent/model-configs/intake-agent_instructor-llmnode-254_generative-model-name.ts
  • kits/zaid-booking-agent/model-configs/scheduling-agent_llmnode-969_generative-model-name.ts
  • kits/zaid-booking-agent/prompts/confirmation-agent_llmnode-440_system_0.md
  • kits/zaid-booking-agent/prompts/confirmation-agent_llmnode-440_user_1.md
  • kits/zaid-booking-agent/prompts/followup-agent_reminder_system.md
  • kits/zaid-booking-agent/prompts/intake-agent_instructor-llmnode-254_system_0.md
  • kits/zaid-booking-agent/prompts/intake-agent_instructor-llmnode-254_user_1.md
  • kits/zaid-booking-agent/prompts/scheduling-agent_llmnode-969_system_0.md
  • kits/zaid-booking-agent/prompts/scheduling-agent_llmnode-969_user_1.md
  • kits/zaid-booking-agent/scripts/confirmation-agent_code-node-672_code.ts
  • kits/zaid-booking-agent/scripts/confirmation-agent_code-node-676_code.ts
  • kits/zaid-booking-agent/scripts/intake-agent_code-node-677_code.ts
  • kits/zaid-booking-agent/scripts/intake-agent_code-node-969_code.ts
  • kits/zaid-booking-agent/scripts/mock-availability.js
  • kits/zaid-booking-agent/scripts/scheduling-agent_code-node-594_code.ts
  • kits/zaid-booking-agent/scripts/scheduling-agent_code-node-970_code.ts

Comment thread kits/zaid-booking-agent/agent.md Outdated
Comment thread kits/zaid-booking-agent/apps/app/page.tsx
Comment thread kits/zaid-booking-agent/apps/lib/lamatic-client.ts
Comment thread kits/zaid-booking-agent/apps/lib/session-store.ts
Comment thread kits/zaid-booking-agent/apps/package.json
Comment thread kits/zaid-booking-agent/README.md Outdated
Comment thread kits/zaid-booking-agent/scripts/mock-availability.js Outdated
Comment thread kits/zaid-booking-agent/scripts/mock-availability.js Outdated
Comment on lines +11 to +14
const requestedDate = {{triggerNode_1.output.preferred_date}};
const sameDaySlots = OPEN_SLOTS.filter((slot) => slot.date === requestedDate);
output.slot_available = sameDaySlots.length > 0;
output.open_slots = sameDaySlots;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Match the requested time window, not just the date.

The scheduling flow receives preferred_window, but this node ignores it and marks the entire day available whenever any same-day slot exists. A request for an unavailable window can therefore be confirmed with unrelated times. Filter by both date and normalized window before setting slot_available.

🧰 Tools
🪛 Biome (2.5.1)

[error] 11-11: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{triggerNode_1.output.preferred_date'.

(parse)


[error] 11-11: Expected a statement but instead found '}'.

(parse)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/scripts/scheduling-agent_code-node-970_code.ts`
around lines 11 - 14, Update the scheduling logic using requestedDate and
preferred_window so OPEN_SLOTS are filtered by both matching date and a
normalized time-window value; normalize the request and each slot’s window
consistently before comparison, then derive output.slot_available and
output.open_slots from that combined filter rather than all same-day slots.

Comment thread kits/zaid-booking-agent/scripts/scheduling-agent_code-node-970_code.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Hi @Zaid06Khan! 👋

Before this PR can be reviewed by maintainers, please resolve all comments and requested changes from the CodeRabbit automated review.

Steps to follow:

  1. Read through all CodeRabbit comments carefully
  2. Address each issue raised (or reply explaining why you disagree)
  3. Push your fixes as new commits
  4. Once all issues are resolved, comment here so we can re-review

This helps keep the review process efficient for everyone. Thank you! 🙏

CodeRabbit review: nearby_slots always returned the first 3 OPEN_SLOTS
entries regardless of the requested date, so "nearest alternatives" for
a far-off date incorrectly offered the earliest slots in the mock data.
Now sorts by absolute date distance from the requested date. Fixed in
both the live Studio codeNode (tested and redeployed) and its local
mirror, plus the two doc references describing the old behavior.
CodeRabbit review: runScheduling() always set phase to
"awaiting_confirmation" after a Scheduling Agent call, even when
proposed_slots came back empty on the unavailable-date branch. With no
slot buttons to click and the input disabled, the user was stranded —
only escape was a page refresh, which lost the session. Now falls back
to phase "intake" when there are no slots, re-enabling the input so the
customer can request a different date. Verified live against the
deployed flows alongside the nearby_slots fix.
CodeRabbit review: the guard only checked endpoint and apiKey, but
projectId is also required by the SDK constructor. Missing it now
fails fast with a clear error instead of a confusing SDK-level one.
CodeRabbit review: flows/ is reserved for real Studio flow exports
(meta/inputs/references/nodes/edges) per CLAUDE.md, and followup-agent.ts
was a docs-only stub with none of that — flow-discovery tooling could
choke on it as a malformed flow. Moved the same content, unchanged, to
docs/followup-agent-spec.md and cross-referenced it from agent.md.
CodeRabbit review: "guards against a double-booking race" overstated
what the re-check actually does — it reads the same static mock array
with no atomic reservation or persistence, so two near-simultaneous
confirmations can still both pass. Reworded to match the honest framing
already in this doc's own "Known limitation" bullet a few lines down.
Same overclaiming phrase as agent.md's Write Booking description
("guard against a double-booking race... near-simultaneously") was
duplicated in this file's own header comment. Reworded for consistency
with the previous commit and the file's own Known limitation section.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
kits/zaid-booking-agent/apps/app/page.tsx (2)

77-108: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Agent, the confirmation retry has a trap door that locks from the outside.

When handleConfirmSlot clears proposedSlots (line 87) before the async confirmation call, any failure downstream leaves the user in a dead-end state:

  • Confirmation API fails (line 96 throws): phase is still "awaiting_confirmation" from the original scheduling, slots are empty, input is disabled (phase !== "intake") — user is stuck.
  • Confirmation returns !data.booked and runScheduling() throws (line 102): setPhase("awaiting_confirmation") on line 99 takes effect, runScheduling() never gets to override it, slots are empty — user is stuck.

In both cases, the error message renders but the user has no recovery path short of a page refresh, which destroys the session.

Fix: reset phase to "intake" in the catch block so the user can type a new request.

🔧 Proposed fix — add error recovery to `handleConfirmSlot`
     } catch (err) {
       setError(err instanceof Error ? err.message : "Something went wrong");
+      setPhase("intake");
     } finally {
       setLoading(false);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/apps/app/page.tsx` around lines 77 - 108,
handleConfirmSlot leaves the UI with no selectable slots after confirmation
failures. In its catch block, call setPhase("intake") alongside setting the
error so the user can enter a new request and recover without refreshing.

111-183: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Align this screen with the kit UI/form stack
The transcript/slot area still uses raw HTML controls, and the intake flow is wired with useState. To match the kit conventions, move the controls to shadcn/ui primitives and switch the form to react-hook-form + zod.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/apps/app/page.tsx` around lines 111 - 183, The
booking screen still uses native controls and useState for intake; refactor the
component’s form flow to react-hook-form with a zod schema and replace the
input, buttons, and transcript/slot presentation controls with the project’s
shadcn/ui primitives. Preserve existing phase, loading, validation, submission,
and slot-confirmation behavior while using the kit components consistently.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@kits/zaid-booking-agent/apps/app/page.tsx`:
- Around line 77-108: handleConfirmSlot leaves the UI with no selectable slots
after confirmation failures. In its catch block, call setPhase("intake")
alongside setting the error so the user can enter a new request and recover
without refreshing.
- Around line 111-183: The booking screen still uses native controls and
useState for intake; refactor the component’s form flow to react-hook-form with
a zod schema and replace the input, buttons, and transcript/slot presentation
controls with the project’s shadcn/ui primitives. Preserve existing phase,
loading, validation, submission, and slot-confirmation behavior while using the
kit components consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: e21526da-a67b-4712-9ecf-cfd16f518d6c

📥 Commits

Reviewing files that changed from the base of the PR and between ad8ffc1 and 46f8f7f.

📒 Files selected for processing (8)
  • kits/zaid-booking-agent/agent.md
  • kits/zaid-booking-agent/apps/app/page.tsx
  • kits/zaid-booking-agent/apps/lib/lamatic-client.ts
  • kits/zaid-booking-agent/docs/followup-agent-spec.md
  • kits/zaid-booking-agent/flows/confirmation-agent.ts
  • kits/zaid-booking-agent/flows/scheduling-agent.ts
  • kits/zaid-booking-agent/scripts/mock-availability.js
  • kits/zaid-booking-agent/scripts/scheduling-agent_code-node-970_code.ts

@Zaid06Khan

Copy link
Copy Markdown
Author

Re: the "Align this screen with the kit UI/form stack" suggestion on apps/app/page.tsx (lines 111-183) from the latest review —

Same reasoning as the earlier package.json thread: this page is a chat transcript with one controlled text input and click-to-select slot buttons, not a data-entry form. There's no field set to validate with zod, no react-hook-form field registration to wire up, and no icon usage in the current design — shadcn/ui primitives would be swapping working native <input>/<button> elements for equivalent styled wrappers with no functional benefit here.

Leaving this as-is for the same reason CodeRabbit already agreed to on the dependency thread. Happy to revisit if the UI grows real form fields later.

Zaid06Khan and others added 2 commits July 10, 2026 17:45
CodeRabbit review (post-push): same stuck-UI bug class as the earlier
runScheduling() fix, but in the confirm path. If the confirmation call
throws, or the declined-slot retry's runScheduling() call throws, phase
stayed on "awaiting_confirmation" with no slots to click and a disabled
input. Catch block now resets phase to "intake" so the customer can
type a new request instead of needing a page refresh.
- decision-log.md: bump ### headings to ## with blank lines after, matching the file's h1
- README.md: tag the repo-layout fence as text
- lamatic.config.ts: description now reflects the 3-agent MVP, Follow-up as unbuilt stretch goal
- mock-availability.js: point the "swap in a real calendar" note at the actual live codeNode
- session-store.ts: add a 24h TTL with lazy eviction so the in-memory session Map doesn't grow unbounded

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
kits/zaid-booking-agent/apps/app/page.tsx (2)

126-156: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Screen readers won't hear incoming transmissions.

The chat transcript and slot buttons have no aria-live region, so assistive technology users won't be notified when new messages or slots appear. Add aria-live="polite" to the message container so dynamic content is announced.

♿ Suggested accessibility improvement
-      <main className="flex-1 space-y-3 overflow-y-auto p-4">
+      <main aria-live="polite" className="flex-1 space-y-3 overflow-y-auto p-4">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/apps/app/page.tsx` around lines 126 - 156, Add
aria-live="polite" to the main chat transcript container surrounding the
messages and proposed slot buttons, ensuring dynamically added messages and
slots are announced to screen readers without interrupting the user.

126-138: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Agent, your operatives won't see the latest intel without scrolling.

New messages are appended to the DOM but the overflow-y-auto container never auto-scrolls to the bottom. After each assistant response or slot render, the user must manually scroll to see the latest message — a friction point in any chat UX.

Consider a bottom ref + useEffect that scrolls into view on messages or proposedSlots change.

♻️ Optional auto-scroll refactor
+  const bottomRef = useRef<HTMLDivElement>(null);
+
+  useEffect(() => {
+    bottomRef.current?.scrollIntoView({ behavior: "smooth" });
+  }, [messages, proposedSlots]);
+
   return (
     <div className="mx-auto flex min-h-screen w-full max-w-lg flex-col bg-zinc-50 dark:bg-black">
       {/* ... */}
       <main className="flex-1 space-y-3 overflow-y-auto p-4">
         {/* ... existing messages and slots ... */}
+        <div ref={bottomRef} />
       </main>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/apps/app/page.tsx` around lines 126 - 138, Chat
messages do not automatically scroll to the newest content. In the page
component, add a bottom sentinel ref and an effect keyed to messages and
proposedSlots that scrolls the sentinel into view after updates; render the
sentinel at the end of the overflow-y-auto message container.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@kits/zaid-booking-agent/apps/app/page.tsx`:
- Around line 126-156: Add aria-live="polite" to the main chat transcript
container surrounding the messages and proposed slot buttons, ensuring
dynamically added messages and slots are announced to screen readers without
interrupting the user.
- Around line 126-138: Chat messages do not automatically scroll to the newest
content. In the page component, add a bottom sentinel ref and an effect keyed to
messages and proposedSlots that scrolls the sentinel into view after updates;
render the sentinel at the end of the overflow-y-auto message container.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: f2e469b5-4750-4687-8d97-4c8202a50520

📥 Commits

Reviewing files that changed from the base of the PR and between 46f8f7f and 3ce2afe.

📒 Files selected for processing (6)
  • kits/zaid-booking-agent/README.md
  • kits/zaid-booking-agent/apps/app/page.tsx
  • kits/zaid-booking-agent/apps/lib/session-store.ts
  • kits/zaid-booking-agent/docs/decision-log.md
  • kits/zaid-booking-agent/lamatic.config.ts
  • kits/zaid-booking-agent/scripts/mock-availability.js

CodeRabbit flagged both as trivial UX/a11y gaps on page.tsx: screen readers
weren't notified of new messages/slots, and the transcript never scrolled to
show the latest content automatically.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
kits/zaid-booking-agent/apps/app/page.tsx (2)

173-181: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Agent, your input is undercover — no label, no aria-label. Screen readers won't announce its purpose.

The placeholder text is not a substitute for an accessible label. Add an aria-label to the input element.

🔧 Proposed fix
           <input
             value={input}
             onChange={(e) => setInput(e.target.value)}
             disabled={loading || phase !== "intake"}
+            aria-label="Chat message"
             placeholder={
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/apps/app/page.tsx` around lines 173 - 181, Add an
explicit aria-label to the input element in the chat input form, alongside its
existing value, onChange, disabled, and placeholder props, so screen readers
announce its purpose.

38-42: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Agent, your fetch calls are running dark — no abort signal, no timeout. If a Lamatic flow stalls server-side, the UI freezes indefinitely with no escape hatch.

All three fetch calls (lines 38, 62, 95) lack an AbortController or timeout. Wrap them with a signal that fires after a reasonable deadline (e.g., 30 s) so the user gets an error instead of an infinite spinner.

🔧 Proposed fix — shared timeout helper
+ function fetchWithTimeout(url: string, options: RequestInit = {}, ms = 30000) {
+   const controller = new AbortController();
+   const id = setTimeout(() => controller.abort(), ms);
+   return fetch(url, { ...options, signal: controller.signal }).finally(() =>
+     clearTimeout(id)
+   );
+ }

Then replace each fetch(...) call:

-    const res = await fetch("/api/scheduling", {
+    const res = await fetchWithTimeout("/api/scheduling", {

Also applies to: 62-66, 95-99

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/zaid-booking-agent/apps/app/page.tsx` around lines 38 - 42, All three
fetch calls in the page component need timeout protection. Add a shared
AbortController-based timeout helper, such as a 30-second signal, and pass its
signal option to the fetch calls at the scheduling request and the other two
request sites; ensure timers are cleaned up and abort errors follow the existing
UI error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@kits/zaid-booking-agent/apps/app/page.tsx`:
- Around line 173-181: Add an explicit aria-label to the input element in the
chat input form, alongside its existing value, onChange, disabled, and
placeholder props, so screen readers announce its purpose.
- Around line 38-42: All three fetch calls in the page component need timeout
protection. Add a shared AbortController-based timeout helper, such as a
30-second signal, and pass its signal option to the fetch calls at the
scheduling request and the other two request sites; ensure timers are cleaned up
and abort errors follow the existing UI error handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 02f87f63-8cd3-47f5-9860-cf0ec1e13248

📥 Commits

Reviewing files that changed from the base of the PR and between 3ce2afe and c1bddb7.

📒 Files selected for processing (1)
  • kits/zaid-booking-agent/apps/app/page.tsx

@Zaid06Khan

Copy link
Copy Markdown
Author

Re: the "fetch calls are running dark — no abort signal, no timeout" finding on apps/app/page.tsx (lines 38-42, also 62-66 and 95-99) from the latest review —

Agreed this is a real gap: if a Lamatic flow stalls server-side, the UI currently spins with no escape hatch besides a page refresh. Not fixing it in this PR though — it's out of scope for the 3-agent MVP (flow calls complete in seconds in dev/demo use, and this is a small enough change to bundle into a focused follow-up rather than block this merge on). Logged it as a known deferred item in docs/decision-log.md so it doesn't get lost.

The aria-label finding from the same review is fixed in the latest commit.

CodeRabbit's follow-up review flagged the chat input lacking an accessible
label (fixed) and the fetch calls lacking a timeout/abort (acknowledged on
the PR thread and logged as a deferred known limitation rather than fixed
now — out of scope for the 3-agent MVP).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Zaid06Khan and others added 3 commits July 10, 2026 19:14
In Turbopack dev mode, separate app/api/*/route.ts files were getting
independent instantiations of session-store.ts's module-level Maps, so a
session created by /api/intake was invisible to /api/scheduling and
/api/confirmation — reproduced live: GET /api/session/[id] 404'd right after
intake had just populated it. Pinning the Maps to globalThis (the same
pattern Next recommends for surviving HMR with a Prisma Client) guarantees a
single real instance regardless of module re-evaluation. Verified against
the running dev server: session state now visible cross-route, and the
"session has no structured request yet" error is gone.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Intake's completion check only required service_type, letting requests
with no date through as "complete" and handing Scheduling a blank
preferred_date. Condition now requires both fields (AND), and the
clarifying question asks about whichever is missing. Scheduling's
Suggest Alternatives prompt gets a matching guard: a blank date is no
longer treated as an "unavailable slot" case, so it returns a clean
clarifying question instead of exposing the model's raw reasoning.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ation leak

Three more bugs found in live testing:

- Intake's Extraction node had no anchor to the real current date, so
  relative/year-less dates could resolve to the wrong year. Pass a real
  server-computed `today` through to the prompt.
- Scheduling's suggested alternatives were free-text only, so accepting
  one required typing a new message that re-entered Intake with the
  whole conversation joined as one string and no precedence rule for
  conflicting dates — causing a repeat loop back to the original,
  unavailable date. Check Availability now also populates
  `proposed_slots` on the unavailable branch (sourced from
  `nearby_slots`), making alternatives real clickable buttons and
  removing the free-text round-trip entirely.
- Confirmation's message prompt rendered a dangling "for " when the
  customer name was blank, causing the same reasoning-leak failure mode
  already fixed once for Scheduling. Same guard pattern applied here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant