Skip to content

Feat: Support Triage [agentkit-challenge]#80

Open
VITianYash42 wants to merge 20 commits intoLamatic:mainfrom
VITianYash42:feat/support-triage
Open

Feat: Support Triage [agentkit-challenge]#80
VITianYash42 wants to merge 20 commits intoLamatic:mainfrom
VITianYash42:feat/support-triage

Conversation

@VITianYash42
Copy link
Copy Markdown

@VITianYash42 VITianYash42 commented Mar 21, 2026

What This Kit Does

Automates customer support by taking inbound tickets and instantly generating a category, sentiment analysis, urgency level, and a draft email response. This saves time, reduces manual routing work, and improves response clarity.

Video Walkthrough: (https://drive.google.com/file/d/192fqT63JLxS9tOcBvN-nEK8ll36xbKhs/view?usp=sharing)

Providers & Prerequisites

  • Lamatic Studio Flow
  • Gemini Free Tier
    (Note: Requires a 60-second cooldown between requests to prevent 429 Rate Limit errors. The Next.js UI explicitly catches and handles this exception.)
    (Note 2: The Lamatic Studio UI currently lacks the 'Export' button on the flow menu as documented in CONTRIBUTING.md, so raw JSON flow files are intentionally omitted.)

How to Run Locally

  1. cd kits/automation/support-triage
  2. npm install
  3. cp .env.example .env.local and fill in values
  4. npm run dev

Live Preview

https://agent-kit-git-feat-suppo-3f22fd-yash-singhals-projects-d43367ba.vercel.app/

Lamatic Flow

Flow ID: c5e67b16-fa77-454d-80d4-77b40adbda38

  • .gitignore — Node.js, Next.js, env, build, TypeScript artifacts ignored (unignores .env.example)
  • package.json — New private Next.js app "lamatic-triage" with lamatic, next, react deps and scripts (dev/build/start/lint)
  • tsconfig.json — TypeScript config (ES2017 target, react-jsx, moduleResolution: bundler, path alias @/*)
  • next.config.ts — Placeholder Next.js config (typed NextConfig)
  • eslint.config.mjs — ESLint flat config using eslint-config-next with custom global ignores
  • postcss.config.mjs — PostCSS config enabling @tailwindcss/postcss plugin
  • config.json — Automation metadata for "AI Support Triage Engine" (name, description, tags, author, steps referencing NEXT_PUBLIC_LAMATIC_FLOW_ID, integrations: Lamatic Studio Flow + Gemini Free Tier, features, demo/github URLs)
  • .env.example — Template vars: LAMATIC_PROJECT_ENDPOINT, LAMATIC_PROJECT_ID, LAMATIC_PROJECT_API_KEY, LAMATIC_FLOW_ID
  • README.md — Kit documentation: purpose, prerequisites (Lamatic Studio Flow + Gemini; 60s cooldown to avoid 429s), local run steps, Lamatic Flow ID placeholder
  • app/globals.css — Global Tailwind + CSS custom properties for background/foreground with light/dark mode and font variable mappings
  • app/layout.tsx — Root Next.js layout: imports globals, initializes Geist fonts bound to CSS variables, exports metadata, renders html/body with layout classes
  • app/page.tsx — Client page with textarea to submit ticket_text to /api/triage; manages ticketText/loading/triageData; handles rate-limit/quota (429) and other errors; renders category/sentiment/urgency cards and draft email; disables UI during loading
  • app/api/triage/route.ts — POST API route: validates required env vars, instantiates Lamatic client, calls lamaticClient.executeFlow(flowId, { ticket_text }), returns flow result or HTTP 500 on errors

Flow file check:

  • No local flow JSON (e.g., flow.json / flow export) was found in the repository under kits/automation/support-triage. Because the Lamatic Studio export JSON is not included, I cannot enumerate the flow node types directly.
  • High-level behavior (from README/config and API wiring):
    • Incoming ticket_text is sent from the frontend to the backend API.
    • The backend invokes a Lamatic Flow (ID: c5e67b16-fa77-454d-80d4-77b40adbda38) which uses Gemini LLM to perform:
      • Category classification
      • Sentiment analysis
      • Urgency/priority detection
      • Auto-draft a response email
    • The frontend displays the triage output and handles rate-limit/quota responses; README and docs recommend a 60-second cooldown to avoid Gemini Free Tier 429 errors.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 21, 2026

Warning

Rate limit exceeded

@github-actions[bot] has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 31 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 29 minutes and 31 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3f83ae6a-f8a5-432f-b17a-13fcf8d20cd2

📥 Commits

Reviewing files that changed from the base of the PR and between d696140 and 688183a.

📒 Files selected for processing (6)
  • kits/automation/support-triage/app/api/triage/route.ts
  • kits/automation/support-triage/app/globals.css
  • kits/automation/support-triage/app/layout.tsx
  • kits/automation/support-triage/app/page.tsx
  • kits/automation/support-triage/flows/.gitkeep
  • kits/automation/support-triage/flows/support-triage-flow/README.md

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

Mission: Established an "AI Support Triage Engine" Next.js kit — adds frontend UI, backend Lamatic API route, project config (TS, ESLint, Tailwind), documentation, and environment templates for running AI-driven ticket triage.

Changes

Cohort / File(s) Summary
Project Setup & Config
kits/automation/support-triage/package.json, kits/automation/support-triage/tsconfig.json, kits/automation/support-triage/next.config.ts, kits/automation/support-triage/eslint.config.mjs, kits/automation/support-triage/postcss.config.mjs, kits/automation/support-triage/.gitignore
Adds package manifest and scripts, TypeScript config with path alias, Next.js placeholder config, flat ESLint config with Next presets and custom global ignores, PostCSS plugin entry for Tailwind, and git ignores for node/Next/build artifacts and env files.
Documentation & Environment
kits/automation/support-triage/README.md, kits/automation/support-triage/.env.example, kits/automation/support-triage/config.json
Adds README describing the kit and run steps, example env file with Lamatic/flow placeholders, and automation metadata/config.json declaring integrations, features, and a flow step tied to NEXT_PUBLIC_LAMATIC_FLOW_ID.
Frontend (App)
kits/automation/support-triage/app/layout.tsx, kits/automation/support-triage/app/page.tsx, kits/automation/support-triage/app/globals.css
Introduces root layout with Google Fonts and exported metadata, global CSS with Tailwind theme mappings and light/dark custom properties, and a client page that posts ticket_text to /api/triage, handling loading, errors (including rate-limit detection), and rendering triage results/drafts.
Backend API
kits/automation/support-triage/app/api/triage/route.ts
Adds POST handler that validates required Lamatic env vars, parses ticket_text from request, calls lamaticClient.executeFlow(flowId, { ticket_text }), and returns the flow result or structured 500 errors on missing config or execution failures.
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly indicates the primary change: adding a Support Triage kit as part of an agentkit challenge, directly aligned with the changeset's main objective.
Description check ✅ Passed The description covers all essential requirements: kit purpose, providers/prerequisites, local run instructions, live preview, and flow ID, though it lacks explicit PR checklist items per the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (4)
kits/automation/support-triage/README.md (1)

16-17: Update placeholder Flow ID.

The Flow ID shows your-flow-id as a placeholder. Consider either removing this line (since users will set it via environment variables) or noting this is obtained from Lamatic Studio after flow creation.

kits/automation/support-triage/app/layout.tsx (1)

15-18: Update boilerplate metadata.

The metadata still contains default "Create Next App" values. Update to reflect the actual kit purpose.

✏️ Suggested metadata
 export const metadata: Metadata = {
-  title: "Create Next App",
-  description: "Generated by create next app",
+  title: "AI Support Triage Engine",
+  description: "Automated customer support ticket categorization, sentiment analysis, and draft response generation",
 };
kits/automation/support-triage/app/globals.css (1)

22-26: Use the configured font variable instead of hardcoded Arial.

The @theme inline block defines --font-sans: var(--font-geist-sans), but the body styles hardcode Arial, Helvetica, sans-serif. Use the Tailwind font variable for consistency with the configured Geist fonts.

✏️ Proposed fix
 body {
   background: var(--background);
   color: var(--foreground);
-  font-family: Arial, Helvetica, sans-serif;
+  font-family: var(--font-sans), Arial, Helvetica, sans-serif;
 }
kits/automation/support-triage/config.json (1)

19-22: Populate public URLs in config for discoverability.

Given this PR already provides a live preview and walkthrough, leaving demoUrl, deployUrl, and documentationUrl empty misses useful kit metadata.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dfad26f1-5b68-4704-bd09-a8fec7c77d22

📥 Commits

Reviewing files that changed from the base of the PR and between e1ceb47 and cbb842d.

⛔ Files ignored due to path filters (7)
  • kits/automation/support-triage/app/favicon.ico is excluded by !**/*.ico
  • kits/automation/support-triage/package-lock.json is excluded by !**/package-lock.json
  • kits/automation/support-triage/public/file.svg is excluded by !**/*.svg
  • kits/automation/support-triage/public/globe.svg is excluded by !**/*.svg
  • kits/automation/support-triage/public/next.svg is excluded by !**/*.svg
  • kits/automation/support-triage/public/vercel.svg is excluded by !**/*.svg
  • kits/automation/support-triage/public/window.svg is excluded by !**/*.svg
📒 Files selected for processing (12)
  • kits/automation/support-triage/.gitignore
  • kits/automation/support-triage/README.md
  • kits/automation/support-triage/app/globals.css
  • kits/automation/support-triage/app/layout.tsx
  • kits/automation/support-triage/app/page.tsx
  • kits/automation/support-triage/app/utils.ts
  • kits/automation/support-triage/config.json
  • kits/automation/support-triage/eslint.config.mjs
  • kits/automation/support-triage/next.config.ts
  • kits/automation/support-triage/package.json
  • kits/automation/support-triage/postcss.config.mjs
  • kits/automation/support-triage/tsconfig.json

Comment on lines +3 to +7
export const lamaticClient = new Lamatic({
endpoint:process.env.NEXT_PUBLIC_LAMATIC_PROJECT_ENDPOINT as string,
projectId: process.env.NEXT_PUBLIC_LAMATIC_PROJECT_ID as string,
apiKey: process.env.NEXT_PUBLIC_LAMATIC_PROJECT_API_KEY as string,
})
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 21, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Security: API key exposed to the browser via NEXT_PUBLIC_ prefix.

Environment variables prefixed with NEXT_PUBLIC_ are bundled into the client-side JavaScript and visible to anyone inspecting the page. The NEXT_PUBLIC_LAMATIC_PROJECT_API_KEY will be exposed in the browser, allowing unauthorized use of your API credentials.

Move API calls to a server-side API route (app/api/triage/route.ts) and use non-prefixed environment variables.

🔒 Recommended approach: Create a server-side API route

Create app/api/triage/route.ts:

import { Lamatic } from 'lamatic';
import { NextRequest, NextResponse } from 'next/server';

const lamaticClient = new Lamatic({
  endpoint: process.env.LAMATIC_PROJECT_ENDPOINT!,
  projectId: process.env.LAMATIC_PROJECT_ID!,
  apiKey: process.env.LAMATIC_PROJECT_API_KEY!,
});

export async function POST(request: NextRequest) {
  const { ticket_text } = await request.json();
  
  const response = await lamaticClient.executeFlow(
    process.env.LAMATIC_FLOW_ID!,
    { ticket_text }
  );
  
  return NextResponse.json(response);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please use server side JWT encryptions

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.

@amanintech, understood! Here's the mission plan to implement server-side JWT authentication to lock down the /api/triage route while keeping all credentials out of the browser.

Mission: Server-side JWT Encryption for /api/triage

  • Add jose for Edge-compatible JWT signing/verification
  • Add JWT_SECRET to .env.example
  • Create /api/token route to issue short-lived JWTs server-side
  • Protect /api/triage route with JWT verification
  • Remove utils.ts (the leaked client)
  • Update page.tsx to fetch a token before calling /api/triage

Here's the overall security flow after these changes:

sequenceDiagram
    participant Browser
    participant TokenServer as /api/token (Server)
    participant TriageServer as /api/triage (Server)
    participant Lamatic

    Browser->>+TokenServer: POST (no credentials)
    TokenServer-->>-Browser: { token: "<signed JWT, 2min TTL>" }
    Browser->>+TriageServer: POST Authorization: Bearer <token>
    TriageServer->>+TriageServer: jwtVerify(token, JWT_SECRET)
    TriageServer->>+Lamatic: executeFlow(flowId, { ticket_text })
    Lamatic-->>-TriageServer: triage result
    TriageServer-->>-Browser: { category, sentiment, urgency, draft }
Loading

Key security properties of this approach:

  • 🔒 LAMATIC_PROJECT_API_KEY, LAMATIC_PROJECT_ID, and JWT_SECRET never leave the server
  • ⏱️ JWTs are short-lived (2 min), limiting replay attack windows
  • 🚫 /api/triage rejects any request without a valid, unexpired JWT
  • ✅ No NEXT_PUBLIC_ prefixes needed anywhere

✏️ Learnings added
Learnt from: amanintech
Repo: Lamatic/AgentKit PR: 80
File: kits/automation/support-triage/app/utils.ts:0-0
Timestamp: 2026-03-27T19:13:29.605Z
Learning: In `kits/automation/support-triage`, the maintainer (amanintech) requires server-side JWT authentication for API routes. Use the `jose` library with an `HS256` short-lived JWT (2-minute TTL) issued by `/api/token` and verified in `/api/triage`. The JWT_SECRET must be a non-NEXT_PUBLIC_ env var. All Lamatic credentials (LAMATIC_PROJECT_ENDPOINT, LAMATIC_PROJECT_ID, LAMATIC_PROJECT_API_KEY, LAMATIC_FLOW_ID) must also be non-NEXT_PUBLIC_ and server-only.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: Lamatic/AgentKit PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-23T17:08:51.738Z
Learning: Applies to kits/**/lib/lamatic-client.ts : Use the `lib/lamatic-client.ts` pattern to initialize the Lamatic SDK with `LAMATIC_API_URL`, `LAMATIC_PROJECT_ID`, and `LAMATIC_API_KEY`

Learnt from: CR
Repo: Lamatic/AgentKit PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-23T17:08:51.738Z
Learning: Applies to kits/**/actions/**/*.ts : Kit server action files (e.g., `actions/orchestrate.ts`) must call Lamatic flows via the SDK and read flow IDs from environment variables

Failed to handle agent chat message. Please try again.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 431fe6de-06eb-4766-89f8-5b0d5cd6b042

📥 Commits

Reviewing files that changed from the base of the PR and between cbb842d and 04f3aad.

📒 Files selected for processing (7)
  • kits/automation/support-triage/.env.example
  • kits/automation/support-triage/.gitignore
  • kits/automation/support-triage/app/api/triage/route.js
  • kits/automation/support-triage/app/globals.css
  • kits/automation/support-triage/app/layout.tsx
  • kits/automation/support-triage/app/page.tsx
  • kits/automation/support-triage/config.json
✅ Files skipped from review due to trivial changes (2)
  • kits/automation/support-triage/.gitignore
  • kits/automation/support-triage/config.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • kits/automation/support-triage/app/layout.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ca9f0c9f-ba30-4ca1-ab93-fda9e0b4cbb1

📥 Commits

Reviewing files that changed from the base of the PR and between 04f3aad and afe8151.

📒 Files selected for processing (1)
  • kits/automation/support-triage/app/page.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
kits/automation/support-triage/app/api/triage/route.ts (2)

12-12: ⚠️ Potential issue | 🟠 Major

Agent, your perimeter is unguarded—hostile payloads may breach.

The API currently trusts client input without validation. A missing, non-string, or empty ticket_text will pass through to the Lamatic provider, causing unnecessary calls and ambiguous failures. This intel was previously transmitted—awaiting implementation.

🛡️ Proposed validation block
-    const { ticket_text } = await request.json();
+    const body = await request.json();
+    const ticket_text =
+      typeof body?.ticket_text === "string" ? body.ticket_text.trim() : "";
+
+    if (!ticket_text) {
+      return NextResponse.json(
+        { error: "ticket_text must be a non-empty string." },
+        { status: 400 }
+      );
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/support-triage/app/api/triage/route.ts` at line 12, Validate
the incoming ticket_text immediately after parsing request.json(): ensure
ticket_text exists, is a string, and is not empty/whitespace; if validation
fails return a 400/Bad Request response with a clear error message instead of
calling the Lamatic provider. Update the code around the const { ticket_text } =
await request.json(); extraction (the request.json() parsing and any subsequent
call to the Lamatic provider) to perform these checks and short-circuit on
invalid input.

19-20: ⚠️ Potential issue | 🟠 Major

Agent, mission control is receiving false positives.

The executeFlow response may include { status: "error", message: ... }, which this route currently returns as HTTP 200. The frontend in page.tsx (lines 26-39) checks for data.error and rate-limit patterns, but a Lamatic error response won't trigger those guards—it'll slip through as "success."

Other kits in this repo check response?.status === "error" and handle accordingly. This intel was previously transmitted—awaiting alignment with established protocol.

🔧 Proposed response handling
     const response = await lamaticClient.executeFlow(flowId, { ticket_text });
-    return NextResponse.json(response);
+    if (response?.status === "error") {
+      return NextResponse.json(
+        { error: response?.message || "Lamatic flow execution failed." },
+        { status: 502 }
+      );
+    }
+
+    return NextResponse.json(response?.result ?? response);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/support-triage/app/api/triage/route.ts` around lines 19 - 20,
The route currently returns lamaticClient.executeFlow(flowId, { ticket_text })
directly as HTTP 200 even when the response is an error object; update the
handler in route.ts to inspect the returned value from lamaticClient.executeFlow
(e.g., check response?.status === "error" or presence of response.message) and
return an appropriate non-200 response (use NextResponse.json with a 4xx/5xx
status or NextResponse.error) when an error status is present, otherwise return
the successful payload via NextResponse.json; reference
lamaticClient.executeFlow, flowId, ticket_text, and NextResponse.json when
making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Around line 4-8: The Lamatic client is being constructed at module load using
non-null assertions (Lamatic and lamaticClient built from
process.env.LAMATIC_PROJECT_ENDPOINT!, LAMATIC_PROJECT_ID!,
LAMATIC_PROJECT_API_KEY!), which will crash the module with a cryptic error if
any env var is missing; change this to either validate env vars up-front with
clear diagnostic messages or lazily create the client at request time via a
factory like getLamaticClient() that checks
process.env.LAMATIC_PROJECT_ENDPOINT/ID/API_KEY and throws or returns a
controlled error; update any callers (e.g., where flowId is checked) to call the
factory and handle/report the explicit error instead of relying on non-null
assertions at import time.
- Line 21: The catch currently types the caught value as any; change it to
unknown (catch(error: unknown)) and explicitly narrow before using it: check if
error is an instance of Error to access error.message/stack, otherwise coerce to
string (e.g., String(error)) before logging/returning. Update the error handling
inside the same route handler in route.ts (the catch(error: any) block) to
perform this narrowing so TypeScript safety is preserved.

---

Duplicate comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Line 12: Validate the incoming ticket_text immediately after parsing
request.json(): ensure ticket_text exists, is a string, and is not
empty/whitespace; if validation fails return a 400/Bad Request response with a
clear error message instead of calling the Lamatic provider. Update the code
around the const { ticket_text } = await request.json(); extraction (the
request.json() parsing and any subsequent call to the Lamatic provider) to
perform these checks and short-circuit on invalid input.
- Around line 19-20: The route currently returns
lamaticClient.executeFlow(flowId, { ticket_text }) directly as HTTP 200 even
when the response is an error object; update the handler in route.ts to inspect
the returned value from lamaticClient.executeFlow (e.g., check response?.status
=== "error" or presence of response.message) and return an appropriate non-200
response (use NextResponse.json with a 4xx/5xx status or NextResponse.error)
when an error status is present, otherwise return the successful payload via
NextResponse.json; reference lamaticClient.executeFlow, flowId, ticket_text, and
NextResponse.json when making this change.
🪄 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: ad30a0ae-20a4-4a81-979e-a620388e7fe7

📥 Commits

Reviewing files that changed from the base of the PR and between afe8151 and d696140.

📒 Files selected for processing (1)
  • kits/automation/support-triage/app/api/triage/route.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
kits/automation/support-triage/app/api/triage/route.ts (2)

22-23: ⚠️ Potential issue | 🟠 Major

Mission gap: Lamatic error payloads can still leak through as HTTP 200.

Line 23 returns raw executeFlow output. If Lamatic returns { status: "error", ... }, clients will treat it as success. Map this to a non-2xx status.

🛠️ Proposed response handling
     const response = await lamaticClient.executeFlow(flowId, { ticket_text });
-    return NextResponse.json(response);
+    if (response?.status === "error") {
+      return NextResponse.json(
+        { error: response?.message || "Lamatic flow execution failed." },
+        { status: 502 }
+      );
+    }
+
+    return NextResponse.json(response?.result ?? response);
#!/bin/bash
set -euo pipefail

echo "== Locate executeFlow call sites and surrounding handling =="
rg -nP --type=ts --type=js -C3 '\bexecuteFlow\s*\('

echo
echo "== Locate Lamatic error-shape checks =="
rg -nP --type=ts --type=js -C3 'response\?\.(status|result)|status\s*===\s*["'"'"']error["'"'"']'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/support-triage/app/api/triage/route.ts` around lines 22 - 23,
The route currently returns lamaticClient.executeFlow output directly (call at
lamaticClient.executeFlow(flowId, { ticket_text }) and return via
NextResponse.json), which can leak Lamatic error payloads as HTTP 200; update
the handler to inspect the returned object (e.g., check response?.status ===
'error' or response?.result?.status === 'error') and map error cases to a
non-2xx HTTP response (use NextResponse.json(response, { status: 400/500 }) with
an appropriate status code and message), otherwise return the successful payload
as before — modify the code around the executeFlow call and the
NextResponse.json return to perform this conditional branching.

20-20: ⚠️ Potential issue | 🟠 Major

Mission gap: validate ticket_text before calling Lamatic.

Line 20 trusts request JSON shape. Reject missing/non-string/empty ticket_text with HTTP 400 before Line 22 to avoid ambiguous provider failures and wasted calls.

✅ Proposed validation
-    const { ticket_text } = await request.json();
+    const body = await request.json();
+    const ticket_text =
+      typeof body?.ticket_text === "string" ? body.ticket_text.trim() : "";
+
+    if (!ticket_text) {
+      return NextResponse.json(
+        { error: "ticket_text must be a non-empty string." },
+        { status: 400 }
+      );
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/support-triage/app/api/triage/route.ts` at line 20, Request
JSON is currently trusted when extracting const { ticket_text } = await
request.json(); — add validation immediately after parsing (before any call to
Lamatic) to reject missing, non-string, or empty/whitespace-only ticket_text
with an HTTP 400 Response; specifically, check typeof ticket_text === 'string'
and ticket_text.trim().length > 0 and return early with a 400 and clear error
message if validation fails so downstream calls to Lamatic (the provider
invocation) are never made with bad input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Around line 9-16: The code reads process.env.LAMATIC_FLOW_ID into flowId but
the kit's metadata exposes NEXT_PUBLIC_LAMATIC_FLOW_ID; update the kit
configuration so the environment variable used by this route is LAMATIC_FLOW_ID
(server-only) instead of NEXT_PUBLIC_LAMATIC_FLOW_ID, and ensure config.json no
longer declares a NEXT_PUBLIC_ variant; keep the route reference to
process.env.LAMATIC_FLOW_ID (flowId) and remove any public export to prevent
leaking server-only Lamatic credentials.
- Around line 4-23: The POST route is unprotected and uses a public env key; add
HS256 JWT verification at the start of the POST handler (before parsing the body
and calling lamaticClient.executeFlow) using the `jose` library and the
server-only `JWT_SECRET` env var to reject requests with invalid/missing bearer
tokens, then proceed only on successful verification; update your config.json
entry from "envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID" to "envKey":
"LAMATIC_FLOW_ID" to keep the flow ID server-only; additionally, validate
`ticket_text` (non-empty string) before calling `Lamatic.executeFlow` and
inspect the Lamatic response (treat response.status >= 400 as an error and map
it to a proper NextResponse with an error status/message) so you never return
raw error payloads directly.

---

Duplicate comments:
In `@kits/automation/support-triage/app/api/triage/route.ts`:
- Around line 22-23: The route currently returns lamaticClient.executeFlow
output directly (call at lamaticClient.executeFlow(flowId, { ticket_text }) and
return via NextResponse.json), which can leak Lamatic error payloads as HTTP
200; update the handler to inspect the returned object (e.g., check
response?.status === 'error' or response?.result?.status === 'error') and map
error cases to a non-2xx HTTP response (use NextResponse.json(response, {
status: 400/500 }) with an appropriate status code and message), otherwise
return the successful payload as before — modify the code around the executeFlow
call and the NextResponse.json return to perform this conditional branching.
- Line 20: Request JSON is currently trusted when extracting const { ticket_text
} = await request.json(); — add validation immediately after parsing (before any
call to Lamatic) to reject missing, non-string, or empty/whitespace-only
ticket_text with an HTTP 400 Response; specifically, check typeof ticket_text
=== 'string' and ticket_text.trim().length > 0 and return early with a 400 and
clear error message if validation fails so downstream calls to Lamatic (the
provider invocation) are never made with bad input.
🪄 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: 4e042d77-24b9-428f-b62e-6babbf20a514

📥 Commits

Reviewing files that changed from the base of the PR and between d696140 and 5c592b7.

📒 Files selected for processing (1)
  • kits/automation/support-triage/app/api/triage/route.ts

Comment on lines +4 to +23
export async function POST(request: NextRequest) {
try {
const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT;
const projectId = process.env.LAMATIC_PROJECT_ID;
const apiKey = process.env.LAMATIC_PROJECT_API_KEY;
const flowId = process.env.LAMATIC_FLOW_ID;

// Fails fast and safely if env vars are missing
if (!endpoint || !projectId || !apiKey || !flowId) {
return NextResponse.json(
{ error: "Missing required Lamatic environment variables on the server." },
{ status: 500 }
);
}

const lamaticClient = new Lamatic({ endpoint, projectId, apiKey });
const { ticket_text } = await request.json();

const response = await lamaticClient.executeFlow(flowId, { ticket_text });
return NextResponse.json(response);
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Verify /api/token route exists =="
fd -i 'route\.ts$' kits/automation/support-triage/app/api/token

echo
echo "== Verify JWT issuance/verification usage in support-triage API routes =="
rg -nP --type=ts -C2 'SignJWT|jwtVerify|HS256|JWT_SECRET|authorization' kits/automation/support-triage/app/api

Repository: Lamatic/AgentKit

Length of output: 245


🏁 Script executed:

# Search entire support-triage codebase for JWT/token references
find kits/automation/support-triage -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name ".env*" -o -name "*.json" \) | head -20

Repository: Lamatic/AgentKit

Length of output: 475


🏁 Script executed:

# Look for jose library usage or JWT references across entire triage kit
rg -i 'jose|jwtverify|signjwt|jwt_secret|authorization.*bearer' kits/automation/support-triage --type=ts --type=tsx --type=json -l

Repository: Lamatic/AgentKit

Length of output: 87


🏁 Script executed:

# Check the actual triage route file to see complete implementation including error handling
cat kits/automation/support-triage/app/api/triage/route.ts

Repository: Lamatic/AgentKit

Length of output: 1186


🏁 Script executed:

# Check config.json and .env files for environment variable naming
find kits/automation/support-triage -name "config.json" -o -name ".env*" | xargs cat 2>/dev/null

Repository: Lamatic/AgentKit

Length of output: 1237


This mission cannot be accepted in its current state: /api/triage is executing privileged Lamatic flows without authentication.

Your route processes API requests on line 4 without verifying bearer tokens. This exposes the Lamatic flow to unauthorized abuse and quota exhaustion. Additionally, your config.json declares NEXT_PUBLIC_LAMATIC_FLOW_ID, but per architectural requirements, all Lamatic credentials must remain server-only non-NEXT_PUBLIC_ environment variables—your code correctly reads LAMATIC_FLOW_ID, creating a configuration inconsistency that will confuse developers.

Critical blockers:

  1. Missing JWT authentication. Gate the route with HS256 JWT verification before line 20 body processing. Use the jose library with tokens issued by an /api/token endpoint (currently missing). The JWT_SECRET environment variable must also be server-only.

  2. config.json environment key violation. Correct "envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID" to "envKey": "LAMATIC_FLOW_ID" to align with .env.example and maintain server-side credential isolation.

🔐 JWT verification patch (before line 20)
 import { Lamatic } from 'lamatic';
+import { jwtVerify } from 'jose';
 import { NextRequest, NextResponse } from 'next/server';

 export async function POST(request: NextRequest) {
   try {
+    const authHeader = request.headers.get("authorization");
+    if (!authHeader?.startsWith("Bearer ")) {
+      return NextResponse.json({ error: "Missing bearer token." }, { status: 401 });
+    }
+
+    const jwtSecret = process.env.JWT_SECRET;
+    if (!jwtSecret) {
+      return NextResponse.json({ error: "Missing JWT_SECRET on server." }, { status: 500 });
+    }
+
+    try {
+      const token = authHeader.slice("Bearer ".length);
+      await jwtVerify(token, new TextEncoder().encode(jwtSecret), {
+        algorithms: ["HS256"],
+      });
+    } catch {
+      return NextResponse.json({ error: "Invalid or expired token." }, { status: 401 });
+    }
+
     const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT;

Outstanding issues from prior review:

  • Validate ticket_text input before passing to executeFlow
  • Map Lamatic response status errors (e.g., response.status >= 400) before returning raw response
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/automation/support-triage/app/api/triage/route.ts` around lines 4 - 23,
The POST route is unprotected and uses a public env key; add HS256 JWT
verification at the start of the POST handler (before parsing the body and
calling lamaticClient.executeFlow) using the `jose` library and the server-only
`JWT_SECRET` env var to reject requests with invalid/missing bearer tokens, then
proceed only on successful verification; update your config.json entry from
"envKey": "NEXT_PUBLIC_LAMATIC_FLOW_ID" to "envKey": "LAMATIC_FLOW_ID" to keep
the flow ID server-only; additionally, validate `ticket_text` (non-empty string)
before calling `Lamatic.executeFlow` and inspect the Lamatic response (treat
response.status >= 400 as an error and map it to a proper NextResponse with an
error status/message) so you never return raw error payloads directly.

@VITianYash42
Copy link
Copy Markdown
Author

@vrijraj The CI checks are now passing. I have implemented secure server-side API routes for the Lamatic client to address the CodeRabbit security flag, and added the required flow schema files to satisfy the validation pipeline. Ready for your review.

@github-actions
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 29, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@VITianYash42
Copy link
Copy Markdown
Author

@vrijraj The structural validation for the flow schema is passing locally, but the GitHub Action is failing at the final step (HTTP 403) when trying to post the validation summary comment and apply the passing label. This appears to be a GitHub Token permissions restriction for workflows triggered from a forked repository. My codebase is ready for review whenever you have a moment.

@vrijraj vrijraj assigned d-pamneja and unassigned d-pamneja and vrijraj Mar 30, 2026
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.

Could you add a live demo link to this file? would allow us to view the functionality better, and allow users to see the kit before forking it. otherwise, LGTM. Thanks! Will check once that is fixed and github action will be handled

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@d-pamneja I already have added the live demo link to the README! You can also test the deployment here: https://agent-kit-ten.vercel.app/

Thanks for the review. Let me know if you need anything else to unblock the merge.

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.

Screenshot 2026-03-31 at 11 37 51 AM If you could resolve the UI Issues here as well. thanks!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@d-pamneja Sorry for that! I had hardcoded the text colors for a dark theme and missed the light mode toggle. I've updated the Tailwind classes to properly support both light and dark system preferences. The Vercel deployment has been automatically updated with the fix.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

4 participants