NinjasPyajamas 9ddbb4a8e5 feat: wire real service agents into chat with LLM tool dispatch + Rivet proxy fix (#3)
# Wire All 4 Microservice Agents Into Chat

Wires all 4 microservice-backed agents into the chat so the LLM can call real services and return session URLs.

---

## Changes

### New

* `src/routes/chat.ts`

  * Added a direct HTTP chat endpoint.
  * When the LLM calls:

    * `start_interview_session`
    * `analyze_resume`
    * `start_roleplay_session`
    * `compute_qscore`
  * The route executes real service probes and returns live session URLs.

---

### Fixed

* `src/index.ts`

  * Rivet proxy now forwards requests to the engine at `localhost:6420`
    instead of using `registry.handler()`.
  * Prevents the:

    ```txt
    Runtime already started as runner
    ```

    conflict.

* `src/actors/user-actor.ts`

  * `receiveMessage()` now returns:

    ```ts
    {
      reply,
      sessions: []
    }
    ```
  * Includes per-module session URLs in responses.

* `docker-compose.yml`

  * Fixed:

    * Gitea health check port
    * Port mapping
    * `A2A_ALLOWED_KEY` default value

* `src/config.ts`

  * Added:

    ```ts
    resumeServiceUrl
    ```
  * Configured to use port `8002`.

---

### Rewritten

* `prompts/system.txt`

  * Reworked into a conversational step-by-step flow.
  * Added explicit rule:

    > CALL THE TOOL IMMEDIATELY

---

### Updated

* `agents/*.md` (6 files)

  * Updated:

    * Domain descriptions
    * Trigger phrases
    * Agent boundaries

---

## Verified

| Agent         | Service                  | Result                      |
| ------------- | ------------------------ | --------------------------- |
| Resume (Mira) | `resume-builder:8002`    | Real analysis               |
| Sara          | `interview-service:8007` | Real Gemini session + URL   |
| Emily         | `roleplay-service:8008`  | Real roleplay session + URL |
| Quinn         | `qscore-service:8000`    | Real Q-Score (~84)          |

---

## Outcome

The chat system can now:

* Trigger real backend agent services directly from LLM tool calls
* Return live session URLs
* Maintain structured multi-agent responses
* Avoid Rivet runtime conflicts
* Support end-to-end conversational workflows across all 4 agents

Reviewed-on: puter/growqr-backend#3
Co-authored-by: NinjasPyajamas <divyansh242805@gmail.com>
Co-committed-by: NinjasPyajamas <divyansh242805@gmail.com>
2026-06-01 09:26:19 +00:00

GrowQR — backend + frontend

A multi-agent platform where every user gets a private Grow Agent (Rivet Kit actor) that orchestrates sub-agents and owns a per-user OpenCode + Gitea Docker stack. See docs/PRD.md for the product spec.

What's wired up

  • Auth: Clerk (frontend + backend JWT verification).
  • DB: Postgres + Drizzle (users, actor registry, container mappings, repos, OpenCode sessions, events).
  • Actors: Rivet Kit — growAgent per user (master) and subAgent (worker), with a real OpenCode Zen / OpenAI-compatible tool-use loop.
  • Per-user containers: Gitea (memory repo) + OpenCode (workflow execution), spawned via dockerode, with admin user + access token bootstrap, ports allocated from a managed pool, lifecycle reconciled on backend boot.
  • Frontend: Next.js 16 with @clerk/nextjs for auth and rivetkit/client for direct actor connections + event streaming.
  • Tool surface available to the Grow Agent: spawn_sub_agent, commit_memory, read_memory, list_memory.

One-time setup

You need three external accounts before running:

  1. Clerk — create an app at https://dashboard.clerk.com → copy the publishable + secret keys.
  2. OpenCode Zen — create an API key at https://opencode.ai/auth.
  3. Docker — Docker Desktop (or any daemon dockerode can reach via /var/run/docker.sock).

Then:

# Backend env
cp .env.example .env
# fill in CLERK_SECRET_KEY, CLERK_PUBLISHABLE_KEY, OPENCODE_API_KEY

# Frontend env
cd growqr-frontend
cp .env.example .env.local
# fill in NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY
cd ..

Running

# 1. Start Postgres + Rivet engine (per-user OpenCode/Gitea containers are
#    spawned dynamically by the backend when a user signs in).
docker compose up -d postgres rivet-engine

# 2. Install + migrate
npm install
npm run db:migrate

# 3. Backend
npm run dev   # http://localhost:4000

# 4. Frontend (separate terminal)
cd growqr-frontend
npm install
npm run dev   # http://localhost:3000

Open http://localhost:3000, sign up, verify your email, and the home page will:

  1. Mirror your Clerk user into Postgres.
  2. Spawn your dedicated Gitea + OpenCode containers (first run pulls images — ~2040s).
  3. Connect the Grow Agent chat to your dedicated Rivet actor.
  4. Stream agent + sub-agent events back to the UI.

Architecture

Browser
   │  Clerk JWT
   ▼
Next.js (3000) ──fetch──▶ /users/bootstrap, /users/me      (Hono on 4000)
   │
   └─Rivet client──▶ /api/rivet/*                          (Hono → registry.handler)
                          │
                          ▼
                  Grow Agent actor  (one per user)
                          │
                          ├─ OpenCode Zen (Kimi K2.6 + tool use)
                          ├─ commit_memory  ────▶  Gitea container (per user)
                          └─ spawn_sub_agent ────▶ OpenCode container (per user)
                                                       (multiplexed sessions)

Useful commands

npm run typecheck          # backend
npm run db:generate        # diff schema → new migration
npm run db:studio          # browse Postgres via Drizzle Studio

cd growqr-frontend
npx tsc --noEmit           # frontend types
npm run lint

Troubleshooting

  • "missing bearer token" from /users/bootstrap — Clerk session not attached. Sign out and back in.
  • Gitea did not become ready during provisioning — Gitea takes 1020s on first pull. Wait, then POST /actors/provision (the frontend retries via polling).
  • OpenCode container exits immediately — check OPENCODE_IMAGE. The compose env passes Cmd: ["serve", ...]; if you swap to a different image, ensure it exposes the opencode serve HTTP surface on :4096.
  • No free ports in USER_PORT_RANGE — bump USER_PORT_RANGE_END in .env or stop unused user stacks via POST /actors/stop.

PRD status

All MVP items in docs/PRD.md §9 are implemented:

  • User auth (Clerk)
  • Actor registry (Postgres + Rivet)
  • One Grow Agent Rivet Kit actor per user
  • Sub-agent registration under the Grow Agent
  • Per-user Gitea Docker + memory repo
  • Memory commits into the user's Gitea
  • Per-user OpenCode Docker + session API
  • Message endpoint from frontend to Grow Agent (via Rivet)
  • Event stream from agent to frontend (via Rivet broadcast)
  • Frontend: login, master chat, sub-agent progress, channel-style logs

Payments and the full quest/pathway runner are deferred to v2 (PRD §10).

Description
No description provided
Readme 1.4 MiB
Languages
TypeScript 95.8%
Dockerfile 2.8%
Shell 1.4%