

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
123456# OpenSearch: AI-Powered Multi-Round Research Agent78## Project Overview910OpenSearch is an AI-powered research agent that conducts sophisticated multi-round web research by:111. **Generating optimized search queries** from user research topics122. **Executing web searches** via Exa API to gather information133. **Reflecting on results** to identify knowledge gaps and determine sufficiency144. **Iteratively searching** with follow-up queries until comprehensive information is gathered155. **Synthesizing comprehensive answers** with proper citations and footnotes1617## Architecture Overview1819The project implements **two parallel architectures** for different use cases:2021### 1. CLI Application (`src/cli/`)22- **Interactive terminal interface** using React + Ink23- **Real-time progress visualization** for each research step24- **Event-driven architecture** with EventEmitter for UI updates25- **Direct BAML integration** for immediate AI function calls26- **Entry point**: `bun run cli`2728### 2. Inngest Workflow (`src/inngest/`)29- **Scalable background processing** using Inngest functions30- **Real-time pub/sub** with channels for live updates31- **Workflow orchestration** with step functions and retry policies32- **Production-ready** with proper error handling and concurrency limits33- **API integration ready** for web applications3435## Key Components & File Structure3637```38opensearch/39├── src/cli/ # CLI Application40│ ├── app.tsx # Main React component with UI orchestration41│ ├── agent.ts # Core agent logic with EventEmitter42│ ├── components/ # UI Components43│ │ ├── research-input.tsx # User input interface44│ │ ├── query-generation.tsx # Query generation display45│ │ ├── search-results.tsx # Search execution progress46│ │ ├── reflection.tsx # Analysis & knowledge gap display47│ │ ├── final-answer.tsx # Answer synthesis display48│ │ └── markdown-renderer.tsx # Markdown rendering with citations49│ ├── types.ts # TypeScript types for workflow steps50│ └── index.tsx # CLI entry point51├── src/inngest/ # Backend Workflow52│ ├── functions/53│ │ ├── deep-research.ts # Main research orchestration function54│ │ ├── execute-searches.ts # Web search execution with rate limiting55│ │ └── index.ts # Function exports56│ ├── client.ts # Inngest client configuration57│ └── connection.ts # Function registration58├── baml_src/ # AI Function Definitions59│ ├── generate_query.baml # Search query generation60│ ├── reflect.baml # Result analysis & gap identification61│ ├── create_answer.baml # Answer synthesis with citations62│ ├── types.baml # Structured data schemas63│ ├── clients.baml # LLM client configurations64│ └── generators.baml # Code generation settings65├── baml_client/ # Auto-generated (DO NOT EDIT)66│ └── [generated TypeScript files]67└── src/utils.ts # Shared utilities68```6970## Research Workflow7172### Step-by-Step Process73741. **Input Collection**75 - User provides research topic76 - Topic validation and preprocessing77782. **Query Generation** (`GenerateQuery` BAML function)79 - AI analyzes research topic80 - Generates optimized search queries81 - Creates **query plan**: specific questions that need answering82 - Returns `SearchQueryList` with queries, rationale, and query plan83843. **Web Search Execution**85 - Parallel execution of search queries via Exa API86 - Rate limiting (5 requests/second) and error handling87 - Collection of search results with highlights and full text88894. **Reflection Analysis** (`Reflect` BAML function)90 - AI analyzes search results for **knowledge gap closure assessment**91 - Tracks answered vs. unanswered questions from query plan92 - Identifies relevant sources containing useful information93 - Determines if current knowledge gap was closed (if any)94 - Assesses overall research sufficiency95965. **Concurrent Processing Phase**97 - **Knowledge Gap Analysis** (`AnalyzeKnowledgeGaps` BAML function):98 - Strategic analysis of knowledge gap history and status99 - Smart abandonment decisions (3-round rule, thoroughness assessment)100 - Selection of next knowledge gap to research101 - Decision on whether to continue research or generate final answer102 - **Fact Extraction** (`ExtractRelevantFacts` BAML function):103 - Extract concise, relevant facts from sources identified by reflection104 - Reduce context length while preserving key information105 - Maintain source attribution for proper citations1061076. **Follow-up Query Generation** (`GenerateFollowUpQueries` BAML function)108 - Generate diverse queries targeting specific knowledge gaps109 - Avoid repetition of previous failed query attempts110 - Strategic query diversity using different angles and terminology111 - Focus on closing identified knowledge gaps1121137. **Iteration Logic**114 - If research insufficient AND gaps worth pursuing: continue with follow-up queries115 - If research sufficient OR all gaps resolved/abandoned: proceed to answer generation116 - Progress tracking with round numbers and knowledge gap status1171188. **Answer Synthesis** (`CreateAnswer` or `CreateAnswerFromFacts` BAML functions)119 - AI synthesizes comprehensive answer from extracted facts or search results120 - Markdown formatting with proper structure121 - Automatic footnote generation with source citations122 - Confidence indicators and knowledge gap acknowledgments123124## BAML Integration Details125126### Core BAML Functions127128#### `GenerateQuery(args: GenerateQueryArgs) -> SearchQueryList`129- **Purpose**: Transform research topic into search queries + structured plan130- **Model**: Gemini 2.5 Flash (fast, cost-effective)131- **Output**: Search queries, rationale, and comprehensive question plan132- **Key Features**: SMART question criteria, current date awareness133134#### `Reflect(summaries, topic, date, queryPlan, answered, unanswered, currentGap, round, maxRounds) -> Reflection`135- **Purpose**: Analyze search results for knowledge gap closure assessment136- **Model**: Gemini 2.5 Flash (fast analysis)137- **Focus**: Gap closure evaluation, question tracking, source identification138- **Output**: Gap closure status, answered questions, relevant sources139- **Key Features**: Conservative gap closure assessment, evidence-based evaluation140141#### `AnalyzeKnowledgeGaps(gapHistory, reflection, queryPlan, currentRound) -> KnowledgeGapAnalysis`142- **Purpose**: Strategic analysis of knowledge gap history and research continuation143- **Model**: Gemini 2.5 Pro (advanced reasoning)144- **Logic**: Smart abandonment criteria, gap prioritization, research strategy145- **Output**: Continue/stop decision, next gap selection, updated gap history146- **Key Features**: 3-round abandonment rule, thoroughness assessment, gap tracking147148#### `ExtractRelevantFacts(relevantSources, topic, queryPlan, reflection, date) -> ExtractedFact[]`149- **Purpose**: Extract concise facts from relevant sources to reduce context length150- **Model**: Gemini 2.5 Flash (efficient extraction)151- **Logic**: Extract only facts relevant to query plan, avoid duplication152- **Output**: Concise facts with source attribution for citations153- **Key Features**: Context optimization, fact relevance filtering, citation preservation154155#### `GenerateFollowUpQueries(targetGap, previousQueries, reflection, queryPlan, currentRound) -> FollowUpQueryGeneration`156- **Purpose**: Generate diverse queries for specific knowledge gaps157- **Model**: Gemini 2.5 Flash (fast query generation)158- **Logic**: Query diversity strategy, avoid repetition, gap-focused targeting159- **Output**: Diverse follow-up queries with strategy explanation160- **Key Features**: Query diversification, gap history awareness, strategic targeting161162#### `CreateAnswer(date, topic, summaries) -> string`163- **Purpose**: Synthesize comprehensive research answer from search results164- **Model**: Gemini 2.5 Pro (high-quality generation)165- **Output**: Markdown-formatted answer with citations166- **Key Features**: Footnote system, confidence indicators, source attribution167168#### `CreateAnswerFromFacts(date, topic, extractedFacts) -> string`169- **Purpose**: Synthesize comprehensive research answer from extracted facts170- **Model**: Gemini 2.5 Pro (high-quality generation)171- **Output**: Markdown-formatted answer with citations172- **Key Features**: Optimized for extracted facts, maintains citation accuracy173174### Data Structures (baml_src/types.baml)175176```typescript177// Core workflow types178SearchQueryList: { queryPlan: string[], query: string[], rationale: string }179Reflection: {180 isSufficient: bool,181 answeredQuestions: int[],182 unansweredQuestions: int[],183 relevantSummaryIds: string[],184 currentGapClosed: bool,185 newGapsIdentified?: string[]186}187SearchResult: { url, id, title, highlights, text, highlightScores }188ExtractedFact: { sourceId, relevantFacts: string[], summary }189190// Knowledge gap tracking types191KnowledgeGapHistory: { gaps: AttemptedKnowledgeGap[], currentGapIndex?: int }192AttemptedKnowledgeGap: {193 description, status: "active"|"abandoned"|"resolved",194 attemptCount, previousQueries: string[],195 relatedQuestionIds: int[], firstAttemptedRound, lastAttemptedRound196}197KnowledgeGapAnalysis: {198 shouldContinueResearch: bool, nextGapToResearch?,199 gapStatus: "new"|"continuing"|"switching"|"complete",200 reasoning, updatedGapHistory: AttemptedKnowledgeGap[]201}202FollowUpQueryGeneration: { queries: string[], rationale, queryStrategy }203```204205## CLI Application Architecture206207### Event-Driven Flow (`src/cli/agent.ts` + `app.tsx`)208209```typescript210// Main workflow steps211type Step =212 | 'input' // User input received213 | 'queries-generated' // Search queries created214 | 'searching' // Web searches in progress215 | 'search-results' // Search results collected216 | 'reflection-complete' // Gap closure analysis finished217 | 'knowledge-gap-analysis' // Strategic gap analysis complete218 | 'followup-query-generation' // Follow-up queries generated219 | 'summarization' // Fact extraction (generating/complete)220 | 'max-steps-reached' // Round limit reached221 | 'answer' // Final answer ready222```223224**Key Features:**225- **Real-time UI updates** via EventEmitter226- **Progress visualization** with round tracking and gap status227- **State management** for complex multi-step workflow with knowledge gap history228- **Concurrent processing** of gap analysis and fact extraction229- **Strategic follow-up query generation** with diversity optimization230- **Error boundaries** and graceful degradation231232### UI Components233234- **ResearchInput**: Text input with submission handling235- **QueryGeneration**: Shows initial + follow-up queries with rationale and round context236- **SearchResults**: Real-time search progress with query status237- **ReflectionStep**: Gap closure analysis and question progress tracking238- **KnowledgeGapAnalysis**: Gap history, abandonment decisions, and next gap selection239- **FollowUpQueryGeneration**: Targeted query generation with diversity strategy240- **FactExtraction**: Concurrent fact extraction progress and results241- **FinalAnswer**: Answer synthesis with extracted facts or search results242- **MarkdownRenderer**: Citation rendering with link handling243244### Event Emission Patterns (`src/cli/agent.ts` → `app.tsx`)245246**CRITICAL**: The CLI uses two different event emission patterns that must be used correctly to avoid duplicate UI components:247248#### `state-update` (Append Pattern)249- **Purpose**: Adds new steps to the workflow250- **Usage**: For genuinely new workflow steps or initial emissions251- **Example**: `eventEmitter.emit('state-update', { type: 'input', data: topic })`252253#### `state-replace` (Replace Pattern)254- **Purpose**: Updates existing steps of the same type (replaces the last occurrence)255- **Usage**: For progress updates or when transitioning from "generating" to "complete" states256- **Example**: `eventEmitter.emit('state-replace', { type: 'searching', data: updatedStatus })`257258#### Common Anti-Patterns to Avoid2592601. **Duplicate UI Components**:261 - ❌ **Wrong**: Emitting both `followup-query-generation` AND `queries-generated` with same data262 - ✅ **Correct**: Only emit `followup-query-generation` for follow-up queries2632642. **Progress Updates**:265 - ❌ **Wrong**: Using `state-update` for search query status changes (creates multiple search components)266 - ✅ **Correct**: Use `state-replace` to update search progress in-place2672683. **Generating → Complete Transitions**:269 - ❌ **Wrong**: `state-update` for fact extraction completion (shows both generating + complete)270 - ✅ **Correct**: `state-replace` to transition from generating to complete state271272#### UI Rendering Logic (`app.tsx`)273274The UI handles "generating" states by checking if steps exist in future indices:275```typescript276const hasFollowUpStep = steps277 .slice(index + 1)278 .some((s) => s.type === 'followup-query-generation');279280// Show generating state only if no complete step exists yet281{!hasFollowUpStep && isLastStep && shouldContinue && (282 <Component isGenerating={true} />283)}284```285286**Key Rule**: If a UI component shows a "generating" state that will be replaced by a "complete" state, the complete state MUST use `state-replace`, not `state-update`.287288## Inngest Workflow Architecture289290### Function Structure (`src/inngest/functions/deep-research.ts`)291292```typescript293// Main orchestration function294deepResearch = inngest.createFunction(295 {296 id: 'deep-research',297 concurrency: { limit: 20 }298 },299 async ({ event, step, logger, publish }) => {300 // 1. Generate initial queries301 // 2. Execute searches in parallel302 // 3. Reflect on results303 // 4. Generate follow-ups or final answer304 // 5. Publish real-time updates305 }306)307```308309**Key Features:**310- **Real-time channels** for live updates311- **Step functions** with automatic retries312- **Concurrent execution** with rate limiting313- **Error handling** with NonRetriableError314- **Logging** throughout workflow315316### Real-time Channels317318```typescript319resultsChannel(uuid)320 .addTopic('initialQueries', SearchQueryList)321 .addTopic('webSearchResults', SearchResult[])322 .addTopic('reflection', Reflection)323 .addTopic('finalAnswer', string)324```325326## Key Utilities (`src/utils.ts`)327328### Citation System329- **processFootnotes()**: Converts random IDs to numbered footnotes330- **insertCitationMarkers()**: Adds citation links to text331- **getCitations()**: Extracts citations from Gemini responses332333### Helper Functions334- **nanoid()**: Generate unique IDs for search results335- **requireEnvironment()**: Environment variable validation336337## Configuration & Environment338339### Required Environment Variables340```bash341EXA_API_KEY= # Exa search API key342GOOGLE_API_KEY= # Google AI (Gemini) API key343ANTHROPIC_API_KEY= # Anthropic (Claude) API key (optional)344OPENAI_API_KEY= # OpenAI API key (optional)345INNGEST_BASE_URL= # Inngest endpoint (for workflow version)346```347348### LLM Client Options (baml_src/clients.baml)349- **Primary**: Google AI (Gemini 2.5 Pro/Flash)350- **Fallback**: OpenAI GPT-4o, Anthropic Claude 3.5 Sonnet351- **Retry policies**: Exponential backoff, constant delay352353## Testing Strategy354355### Integration Tests356- **Manual testing script**: `scripts/test-follow-up-queries.ts`357- **BAML function tests**: `test/generate-query.test.ts`358- **Real API integration**: Uses actual Exa + BAML calls359360### Test Coverage361- Follow-up query generation and execution362- Multi-round workflow progression363- Question tracking and completion364- Citation processing and footnote generation365366## Usage Examples367368### CLI Usage369```bash370bun run cli # Start interactive CLI371bun run dev # Development mode with watching372bun test # Run all tests373bun test test/specific.test.ts # Run specific test374```375376### Complex Research Example377```378Topic: "Compare fintech vs healthtech startup funding in 2024"379380Round 1: General funding queries381├── Reflection: Missing healthtech-specific data382Round 2: Healthtech-focused follow-up queries383├── Reflection: Missing comparative analysis384Round 3: Comparative analysis queries385└── Final Answer: Comprehensive comparison with metrics386```387388## Production Considerations389390### Rate Limiting391- **Exa API**: 5 requests/second (handled automatically)392- **LLM APIs**: Retry policies with exponential backoff393- **Concurrency**: Limited to 20 concurrent workflows394395### Error Handling396- **Network failures**: Automatic retries with backoff397- **API limits**: Graceful degradation and queuing398- **Malformed responses**: Validation and fallbacks399- **Max rounds**: Prevents infinite loops400401### Monitoring402- **Inngest dashboard**: Workflow execution monitoring403- **Step-by-step logging**: Detailed execution traces404- **Real-time channels**: Live progress updates405406## Development Workflow407408### Code Organization409- **CLI logic**: Event-driven with React components410- **Backend logic**: Step functions with proper error handling411- **BAML functions**: Declarative AI function definitions412- **Shared utilities**: Citation processing and helpers413- **Type safety**: Strict TypeScript throughout414415### Key Design Principles416- **Iterative research**: Multi-round approach mimics human research417- **Conservative early, decisive late**: Reflection strategy adapts by round418- **Source attribution**: Proper citations with footnotes419- **Real-time feedback**: Progress visibility throughout process420- **Graceful degradation**: Handles API failures and edge cases421422This architecture provides both immediate interactive research (CLI) and scalable background processing (Inngest) while maintaining consistent AI-powered research quality through BAML function integration.423
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| K-Mistele/opensearchAGENTS.md · 30 | AGENTS.md | buildtestlint-formatstyle+2 | 94/100 | 14 days ago | |
| K-Mistele/opensearch.cursor/rules/baml.mdc · 30 | Cursor rules | style | 44/100 | 14 days ago | |
| K-Mistele/opensearch.cursor/rules/default.mdc · 30 | Cursor rules | buildtestlint-formatstyle+2 | 94/100 | 14 days ago | |
| K-Mistele/opensearch.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc · 30 | Cursor rules | setupteststyle | 73/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/k-mistele-opensearch-cursor-rules-opensearch-project-structure)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.