Skip to content

Conversational AI Agents

The agents/ directory contains four AI agents that drive the corporate profile onboarding flow. They are instantiated synchronously inside HTTP request handlers (in routes/routes.js) — not as background jobs — and collaborate to gather user info, research a company online, and produce a finalized profile draft.

For asynchronous AI workers that operate on the job queue, see User-Specific AI Jobs.


Overview

Agent File Model Role
ConversationAgent agents/conversationAgent.js Gemini 2.5 Flash Orchestrates the onboarding dialog; tracks state
InputParserAgent agents/inputParserAgent.js Gemini 2.5 Flash Extracts structured fields from free-text replies
ResearchAgent agents/researchAgent.js Gemini 2.5 Flash + Google Search tool Web-researches the company and drafts a 9-section profile
ProfileAgent agents/profileAgent.js Gemini 2.5 Flash Refines the research draft into a final profile, handles approval

All four use the @google/generative-ai SDK with the GEMINI_API_KEY env var (see Configuration Reference).


Onboarding Flow

The four agents are not invoked as a strict sequential pipeline. They are instantiated per-session and called conditionally, based on the conversation's state machine. The diagram below shows the typical happy-path order; the actual orchestration in routes/routes.js is closer to "session-managed conditional flow" than a fixed pipeline.

┌──────────────┐
│ Client / UI  │
└──────┬───────┘
       │ POST onboarding messages
┌────────────────────────────────────────────────────────────┐
│ routes/routes.js (per-session agent instances)             │
│                                                            │
│   ConversationAgent ──► InputParserAgent (sub-agent)       │
│         │                                                  │
│         ├── once enough info collected ──►  ResearchAgent  │
│         │                                       │          │
│         │                                       ▼          │
│         │                                  Google Search   │
│         │                                       │          │
│         │      ◄── 9-section research draft ────┘          │
│         │                                                  │
│         └──► ProfileAgent ──► finalized profile JSON       │
└────────────────────────────────────────────────────────────┘

Each session keeps its own agent instances; nothing is persisted to memory beyond the lifetime of the request chain. State is stored in the database once the user approves the profile.


ConversationAgent

File: agents/conversationAgent.js

Role: Multi-turn dialog manager. Greets the user, collects personal details (first/last name, email, phone) and company details (name, website, city, country), then triggers research.

Public methods

Method Inputs Returns
handle_input(update_type, value, session_state) Form-style field updates { message, extracted_field, user_info }
process_user_input(user_input, session_state) Free-form text reply { message, extracted_fields, ...flags }

State

The agent maintains: - conversation_history — array of {role, content} for prompt context - user_info — accumulated field values - Flags: first_name_set, details_confirmed, profile_rejected, waiting_for_profile_decision

System prompt (summary)

A friendly corporate-profile assistant. Greets by name, acknowledges form completions, asks for missing fields, confirms profile creation readiness, and suggests edits when the user rejects. Responses stay 50–100 words; emojis (😄, 🚀, 🌟) are used sparingly.

Sub-agent

ConversationAgent instantiates one InputParserAgent internally and uses it whenever it processes free-text input. After the profile is confirmed, the parser is disabled to prevent further field extraction.


InputParserAgent

File: agents/inputParserAgent.js

Role: A pure JSON extractor. Given a chunk of natural-language input, returns whichever of the eight onboarding fields it can identify.

Public methods

Method Inputs Returns
parse_input(user_input) Raw user text { extracted_info: {...}, website_not_ready: boolean }

Extracted fields

first_name, last_name, phone_number, email_id, company_name, company_website, city, country.

Notes

  • Returns an empty object if nothing is detected — never invents values.
  • Detects "no website" / "site not ready" phrases and sets website_not_ready: true.
  • Has a disabled flag toggled by ConversationAgent once the profile is confirmed.

ResearchAgent

File: agents/researchAgent.js

Role: Generates a draft corporate profile by web-searching the company. Uses Gemini 2.5 Flash with the googleSearch: {} built-in tool — no separate scraping pipeline.

Public methods

Method Inputs Returns
research_company(company_name, company_website, location, streamCallback?) Company metadata; optional stream callback Plain-text profile (9 numbered sections)

Output format

Numbered sections: 1. Company Overview 2. Market Positioning 3. Products & Services 4. Leadership Team 5. Awards & Recognition 6. Recent News 7. Contact Information 8. Online Presence 9. Notable Customers / Partners

Missing fields are rendered as Unknown.

Streaming

If streamCallback is provided, the agent emits incremental events: - research_chunk — partial text as it streams in - research_complete — final string - research_error — on failure (a fallback string is also returned)

Streaming is consumed via Server-Sent Events (SSE) — the calling route handler in routes/routes.js writes incremental events directly to the HTTP response with res.write('data: ...\n\n'). The previous version of this doc claimed Socket.IO; that was incorrect. Socket.IO references in routes/routes.js are commented out (lines 38–39).


ProfileAgent

File: agents/profileAgent.js

Role: Polishes the research output into the final, user-approved profile. Also processes the user's yes/no approval response.

Public methods

Method Inputs Returns
create_profile(user_info, research_data, generate_detailed, streamCallback?) Collected fields + research text Final profile text
handle_approval(user_response, first_name, company_name) "yes" / "no" / free text { status: "completed" \| "pending", profile? }

Output format

Maintains the same 9-section format as ResearchAgent, but with user-provided details merged in, formatting normalized, and tone consistent with the user's onboarding chat.

Streaming

Like ResearchAgent, optional callback events: profile_chunk, profile_complete.


Integration with Routes

routes/routes.js is the only caller. It instantiates a fresh set of agents per onboarding session and chains them:

const ConversationAgent = require('../agents/conversationAgent');
const ResearchAgent = require('../agents/researchAgent');
const ProfileAgent = require('../agents/profileAgent');
// InputParserAgent is created internally by ConversationAgent.

const conv = new ConversationAgent(initialUserInfo);
const research = new ResearchAgent();
const profile = new ProfileAgent();

The route handler holds these instances in memory for the duration of the conversation. There is no shared agent pool — closing the session releases them.


Operational Notes

  • Stateless across sessions — agent state lives in the request handler. Restarting the server drops all in-flight conversations.
  • No retry logic — if Gemini returns an error mid-conversation, the route returns a fallback response and the user is asked to try again.
  • No content moderation — outputs are not filtered for PII or unsafe content beyond what Gemini's own safety settings provide.
  • Cost — each completed onboarding makes 5–15 Gemini calls (parser + conversation turns + research + profile). Monitor under GEMINI_API_KEY usage in GCP.
  • Streaming — when streaming is enabled, output goes to the HTTP response via Server-Sent Events (res.write), not Socket.IO. See the streaming notes on ResearchAgent and ProfileAgent above.

  • User-Specific AI Jobs — async AI workers that run after onboarding completes (brand positioning, objectives, recommended subjects).
  • RAG Pipeline — once a profile is saved, RAG corpora are built per account and used for content generation.
  • Integration Inventory — full Gemini / Vertex AI configuration.