-
Notifications
You must be signed in to change notification settings - Fork 136
feat: Add Startup-Research AgentKit [agentkit-challenge] #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
0b10129
feat: Add Founder Lens - AI Startup Research Agent
cyber-turtle c5126a2
docs: align README with challenge rubric
cyber-turtle 7317720
chore: add vercel demo url to config.json
cyber-turtle db1b262
docs: clarify Exa.ai API node configuration
cyber-turtle 30ae731
fix: improve UX for founder-lens - fix progress bar timing, add timeo…
cyber-turtle fbef69d
docs: add JSDoc docstrings to improve coverage to > 80% and satisfy P…
cyber-turtle 4e1b062
Update kits/agentic/founder-lens/components/IdeaForm.tsx
cyber-turtle 5220ade
addressing Search count mismatch in analyze README
cyber-turtle 72d4862
docs: resolve search count inconsistencies and fix markdown linting i…
cyber-turtle 324999a
Update kits/agentic/founder-lens/lib/lamatic-client.ts
cyber-turtle ee4fd4f
fix: add timeout to chatWithBrief and resolve icon/CSS/doc issues
cyber-turtle 23020e1
fix: disable suggested questions during loading in ChatInterface and …
cyber-turtle 86bd0cc
Update kits/agentic/founder-lens/components/IdeaForm.tsx
cyber-turtle 5bc518b
Revert "Update kits/agentic/founder-lens/components/IdeaForm.tsx"
cyber-turtle 7c8e01e
feat: increase analyzeIdea timeout to 5 minutes
cyber-turtle 7353d11
feat: increase analysis timeout to 10mins and add 'taking longer than…
cyber-turtle 84c41d8
fix: improve JSON parsing robustness in BriefDisplay
cyber-turtle 9ee28f4
fix: add maxDuration for Vercel and adjust UI message timing
cyber-turtle 1b48e23
fix: move maxDuration from server action file to page to fix build error
cyber-turtle 5418926
fix: adjust timeout to 300s to satisfy Vercel Hobby plan limits
cyber-turtle 67b4719
Merge branch 'main' into feat/founder-lens
cyber-turtle d837f51
docs: add live demo link to README
cyber-turtle a330b6d
docs: add screenshot to README
cyber-turtle 879aa15
docs: add screenshot file to repository
cyber-turtle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| FOUNDER_LENS_ANALYZE_FLOW_ID="YOUR_ANALYZE_FLOW_ID" | ||
| FOUNDER_LENS_CHAT_FLOW_ID="YOUR_CHAT_FLOW_ID" | ||
| LAMATIC_API_URL="YOUR_API_ENDPOINT" | ||
| LAMATIC_PROJECT_ID="YOUR_PROJECT_ID" | ||
| LAMATIC_API_KEY="YOUR_API_KEY" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| node_modules/ | ||
| .next/ | ||
| .env.local | ||
| .env | ||
| .DS_Store | ||
| *.log |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| # Founder Lens — AI Startup Research Agent | ||
|
|
||
| > Get a brutally honest investor-grade brief on your startup idea — built from real web data in ~90 seconds. Then chat with your analysis using RAG-powered persistent memory. | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| --- | ||
|
|
||
| ## 1. The Problem | ||
|
|
||
| Non-technical founders spend weeks manually researching whether their idea is viable. They scour Reddit, Crunchbase, and postmortems — and still miss critical blind spots. They need an investor-grade analysis without spending thousands of dollars or hundreds of hours on manual data collection. | ||
|
|
||
| --- | ||
|
|
||
| ## 2. The Approach | ||
|
|
||
| Founder Lens completely automates this research process in ~90 seconds using a 7-phase autonomous agent. Submit a startup idea and two Lamatic flows run in sequence: | ||
|
|
||
| **Flow 1 — Analyze:** Deconstructs your idea into 8 targeted search queries, then fires 9 parallel Exa.ai web searches across: | ||
| - **Market size** — TAM/SAM/SOM data | ||
| - **VC funding signals** — Crunchbase trends and recent rounds | ||
| - **Direct competitors** — mapping the competitive landscape | ||
| - **Failed startup postmortems** — what already tried and died | ||
| - **Customer complaints** — verbatim from Reddit, G2, HN, Capterra | ||
| - **LinkedIn complaint signals** — professional pain signal mining | ||
| - **Success stories** — IndieHackers, YC, TechCrunch breakouts | ||
| - **Business model benchmarks** — pricing and monetization data | ||
| - **Unfair advantage signals** — what makes winners different | ||
|
|
||
| Then a dedicated **Contrarian VC Persona** runs a separate pass to find the fatal flaw. The synthesized result is a structured Founder Brief stored in **Weaviate vector DB** and **Lamatic semantic memory**. | ||
|
|
||
| **Flow 2 — Chat:** The founder sends messages and the system retrieves the stored brief via RAG + semantic memory and answers questions using GPT-4o with full context of the brief and conversation history. | ||
|
|
||
| --- | ||
|
|
||
| ## 3. The Result | ||
|
|
||
| Founder Lens saves founders immense time, reduces manual work entirely, and provides extreme clarity. It delivers the exact brief a VC analyst would write internally before taking a meeting, creating a repeatable workflow for testing new startup ideas before writing a single line of code. | ||
|
|
||
| --- | ||
|
|
||
| ## 4. Tradeoffs & Assumptions | ||
|
|
||
| **Tradeoffs:** | ||
| - **Speed vs. Exhaustive Depth:** We chose to run 9 highly targeted parallel searches to keep the analysis under 90 seconds. We trade off multi-hour, deeply exhaustive agentic crawling for immediate, highly actionable insights. | ||
| - **Frictionless UX:** The chat history is maintained in Lamatic semantic memory. Because we wanted a frictionless UX, we generate a unique `userId` and `sessionId` in `localStorage` automatically instead of requiring users to create accounts and log in securely. | ||
|
|
||
| **Assumptions:** | ||
| - We assume the user's idea revolves around software/tech. Extremely niche physical hardware, biotech, or offline local services might not yield as much verbatim complaint data on Reddit or G2. | ||
| - The high quality of the analysis assumes Exa.ai can successfully retrieve highly semantic, relevant forum threads and news articles based on the generated keyword queries. | ||
|
|
||
| --- | ||
|
|
||
| ## Tech Stack | ||
|
|
||
| | Layer | Technology | | ||
| |---|---| | ||
| | Flow orchestration, RAG, memory | **Lamatic.ai** | | ||
| | Neural web search (9 parallel) | **Exa.ai** | | ||
| | Analysis synthesis & chat | **OpenRouter / GPT-4o** | | ||
| | Idea deconstruction | **OpenRouter / Claude 3.5 Sonnet** | | ||
| | Vector embeddings | **Gemini gemini-embedding-001** | | ||
| | Vector database | **Weaviate** (via Lamatic) | | ||
| | Frontend | **Next.js 14** (TypeScript, Tailwind CSS) | | ||
|
|
||
| --- | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Node.js 18+ | ||
| - A [Lamatic.ai](https://lamatic.ai) account with both flows deployed | ||
| - An OpenRouter API key (configured in Lamatic as a credential) | ||
| - A Gemini API key (configured in Lamatic as a credential) | ||
| - **An Exa.ai API key:** You must create an account on [Exa.ai](https://exa.ai) to get an API key. Once you import the Analyze flow into Lamatic, click on each individual Exa search node. Under the Headers section, manually input your API key into the `x-api-key` field (as a key-value pair). | ||
|
|
||
| --- | ||
|
|
||
| ## Setup Instructions | ||
|
|
||
| 1. **Clone and navigate to the kit folder** | ||
| ```bash | ||
| git clone https://github.com/Lamatic/AgentKit.git | ||
| cd AgentKit/kits/agentic/founder-lens | ||
| ``` | ||
|
|
||
| 2. **Install dependencies** | ||
| ```bash | ||
| npm install | ||
| ``` | ||
|
|
||
| 3. **Set up environment variables** | ||
| ```bash | ||
| cp .env.example .env.local | ||
| ``` | ||
| Then fill in `.env.local` with your real values (see table below). | ||
|
|
||
| 4. **Start the development server** | ||
| ```bash | ||
| npm run dev | ||
| ``` | ||
|
|
||
| 5. **Open your browser** | ||
| ``` | ||
| http://localhost:3000 | ||
| ``` | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| --- | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Description | Where to Find | | ||
| |---|---|---| | ||
| | `FOUNDER_LENS_ANALYZE_FLOW_ID` | Flow ID for the analysis flow | Lamatic Studio → your flow → three-dot menu → Flow ID | | ||
| | `FOUNDER_LENS_CHAT_FLOW_ID` | Flow ID for the chat flow | Lamatic Studio → your flow → three-dot menu → Flow ID | | ||
| | `LAMATIC_API_URL` | Your project API endpoint | Lamatic Studio → Settings → API Docs | | ||
| | `LAMATIC_PROJECT_ID` | Your project ID | Lamatic Studio → Settings → Project | | ||
| | `LAMATIC_API_KEY` | Your API key | Lamatic Studio → Settings → API Keys | | ||
|
|
||
| --- | ||
|
|
||
| ## Flows | ||
|
|
||
| ### Analyze Flow | ||
| **Input:** `{ idea: string, userId: string, sessionId: string }` | ||
| **Output:** `{ brief: string (JSON), decomposition: string (JSON) }` | ||
|
|
||
| Runs the full 7-phase research pipeline, synthesizes a Founder Brief JSON, and stores it in Weaviate + semantic memory. | ||
|
|
||
| ### Chat Flow | ||
| **Input:** `{ message: string, userId: string, sessionId: string }` | ||
| **Output:** `{ answer: string }` | ||
|
|
||
| Retrieves the indexed brief and conversation history from memory, then answers the founder's question with full context. | ||
|
|
||
| > **Important:** The analyze flow must run first for a given `userId` + `sessionId` pair before the chat flow has any context to retrieve. | ||
|
|
||
| --- | ||
|
|
||
| ## Deploy to Vercel | ||
|
|
||
| 1. Push your branch to GitHub: | ||
| ```bash | ||
| git checkout -b feat/founder-lens | ||
| git add kits/agentic/founder-lens/ | ||
| git commit -m "feat: Add Founder Lens - AI Startup Research Agent" | ||
| git push origin feat/founder-lens | ||
| ``` | ||
|
|
||
| 2. Go to [vercel.com](https://vercel.com) and import your repo | ||
|
|
||
| 3. Set the **root directory** to `kits/agentic/founder-lens` | ||
|
|
||
| 4. Add all environment variables from the table above | ||
|
|
||
| 5. Click **Deploy** | ||
|
|
||
| --- | ||
|
|
||
| ## Contributing | ||
|
|
||
| This kit was built for the [agentkit-challenge](https://github.com/Lamatic/AgentKit). To open a PR: | ||
|
|
||
| ``` | ||
| github.com/Lamatic/AgentKit/compare/main...YOUR-USERNAME:feat/founder-lens?expand=1 | ||
| ``` | ||
|
|
||
| Add the `agentkit-challenge` label to your PR. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| "use server"; | ||
|
|
||
| import { lamaticClient } from "@/lib/lamatic-client"; | ||
| import { config } from "../orchestrate.js"; | ||
|
|
||
| export async function analyzeIdea( | ||
| idea: string, | ||
| userId: string, | ||
| sessionId: string | ||
| ): Promise<{ success: boolean; brief?: string; decomposition?: string; error?: string }> { | ||
| try { | ||
| const flow = config.flows.analyze; | ||
| if (!flow.workflowId) throw new Error("FOUNDER_LENS_ANALYZE_FLOW_ID is not set."); | ||
| const resData = await lamaticClient.executeFlow(flow.workflowId, { idea, userId, sessionId }); | ||
| const brief = resData?.result?.brief; | ||
| if (!brief) throw new Error("No brief returned from analyze flow."); | ||
| return { success: true, brief, decomposition: resData?.result?.decomposition }; | ||
| } catch (error) { | ||
| return { success: false, error: error instanceof Error ? error.message : "Unknown error" }; | ||
| } | ||
| } | ||
|
|
||
| export async function chatWithBrief( | ||
| message: string, | ||
| userId: string, | ||
| sessionId: string | ||
| ): Promise<{ success: boolean; answer?: string; error?: string }> { | ||
| try { | ||
| const flow = config.flows.chat; | ||
| if (!flow.workflowId) throw new Error("FOUNDER_LENS_CHAT_FLOW_ID is not set."); | ||
| const resData = await lamaticClient.executeFlow(flow.workflowId, { message, userId, sessionId }); | ||
| const answer = resData?.result?.answer; | ||
| if (!answer) throw new Error("No answer returned from chat flow."); | ||
| return { success: true, answer }; | ||
| } catch (error) { | ||
| return { success: false, error: error instanceof Error ? error.message : "Unknown error" }; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| @import url('https://fonts.googleapis.com/css2?family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700&display=swap'); | ||
|
|
||
| @tailwind base; | ||
| @tailwind components; | ||
| @tailwind utilities; | ||
|
|
||
| :root { | ||
| --background: #000000; | ||
| --foreground: #ffffff; | ||
| --border: rgba(255, 255, 255, 0.08); | ||
| --primary: #ffffff; | ||
| --primary-foreground: #000000; | ||
| --muted: rgba(255, 255, 255, 0.05); | ||
| --muted-foreground: rgba(255, 255, 255, 0.5); | ||
| } | ||
|
|
||
| @layer base { | ||
| * { | ||
| border-color: var(--border); | ||
| box-sizing: border-box; | ||
| } | ||
| body { | ||
| background-color: var(--background); | ||
| color: var(--foreground); | ||
| font-family: "Google Sans", sans-serif; | ||
| font-optical-sizing: auto; | ||
| font-variation-settings: "GRAD" 0; | ||
| -webkit-font-smoothing: antialiased; | ||
| -moz-osx-font-smoothing: grayscale; | ||
| } | ||
| } | ||
|
|
||
| /* --- LIQUID GLASS --- */ | ||
|
|
||
| .liquid-glass { | ||
| background: linear-gradient(135deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.01) 100%); | ||
| backdrop-filter: blur(40px) saturate(150%); | ||
| -webkit-backdrop-filter: blur(40px) saturate(150%); | ||
| border: 1px solid rgba(255, 255, 255, 0.1); | ||
| box-shadow: | ||
| 0 8px 32px 0 rgba(0, 0, 0, 0.37), | ||
| inset 0 1px 1px 0 rgba(255, 255, 255, 0.1); | ||
| border-radius: 1.25rem; | ||
| } | ||
|
|
||
| .liquid-glass-pill { | ||
| background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.02) 100%); | ||
| backdrop-filter: blur(20px) saturate(120%); | ||
| border: 1px solid rgba(255, 255, 255, 0.12); | ||
| box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.15); | ||
| border-radius: 9999px; | ||
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | ||
| } | ||
| .liquid-glass-pill:hover { | ||
| background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.05) 100%); | ||
| transform: translateY(-1px); | ||
| } | ||
|
|
||
| .glass-panel { | ||
| background: rgba(255, 255, 255, 0.03); | ||
| backdrop-filter: blur(20px); | ||
| -webkit-backdrop-filter: blur(20px); | ||
| border: 1px solid rgba(255, 255, 255, 0.06); | ||
| box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); | ||
| border-radius: 1.5rem; | ||
| } | ||
|
|
||
| /* --- AURORA BG --- */ | ||
|
|
||
| .aurora-bg { | ||
| position: fixed; | ||
| top: 0; left: 0; | ||
| width: 100vw; height: 100vh; | ||
| z-index: -1; | ||
| overflow: hidden; | ||
| background-color: #000; | ||
| } | ||
|
|
||
| /* --- PROSE --- */ | ||
|
|
||
| .prose-sleek h1 { font-size: 1.25rem; font-weight: 500; color: #fff; margin-bottom: 0.5rem; } | ||
| .prose-sleek h2 { font-size: 1rem; font-weight: 500; color: #fff; margin-top: 1rem; margin-bottom: 0.25rem; } | ||
| .prose-sleek p { font-size: 0.875rem; line-height: 1.7; color: rgba(255,255,255,0.75); } | ||
| .prose-sleek ul { list-style: disc; padding-left: 1.25rem; color: rgba(255,255,255,0.7); } | ||
| .prose-sleek li { font-size: 0.875rem; margin-bottom: 0.25rem; } | ||
| .prose-sleek strong { font-weight: 600; color: #fff; } | ||
|
|
||
| /* --- SCROLLBAR --- */ | ||
|
|
||
| .custom-scrollbar::-webkit-scrollbar { width: 6px; } | ||
| .custom-scrollbar::-webkit-scrollbar-track { background: transparent; } | ||
| .custom-scrollbar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 10px; } | ||
| .custom-scrollbar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.2); } | ||
|
|
||
| /* --- CURSOR BLINK --- */ | ||
|
|
||
| .cursor-blink { animation: blink 1s step-end infinite; } | ||
| @keyframes blink { 0%,100% { opacity: 1; } 50% { opacity: 0; } } |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import type { Metadata } from "next"; | ||
| import "./globals.css"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "Founder Lens | AI Startup Research Agent", | ||
| description: | ||
| "multi-phase agentic startup research agent. Submit a startup idea and get a brutally honest investor-grade brief built from real web data.", | ||
| }; | ||
|
|
||
| export default function RootLayout({ | ||
| children, | ||
| }: { | ||
| children: React.ReactNode; | ||
| }) { | ||
| return ( | ||
| <html lang="en" className="dark"> | ||
| <body>{children}</body> | ||
| </html> | ||
| ); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.