This document provides essential guidelines for AI models interacting with this LangChain playground project. Adhering to these standards ensures consistency, maintains code quality, and helps AI agents understand the project's architecture and conventions.
LangChain Playground - A TypeScript-based playground for LangChain.js, LangGraph, Slack bot integration, and Model Context Protocol (MCP) with multiple LLM provider support. The project provides both REST API endpoints and Slack bot integration for interacting with different language models and advanced workflow orchestration.
Key Technologies:
- Framework: LangChain.js for building LLM applications
- Workflow: LangGraph for advanced multi-step processes
- Integration: Slack Bolt for Slack app functionality
- Protocol: Model Context Protocol (MCP) for LLM-powered tools
- Server: Fastify for REST API endpoints
- Storage: Redis for caching and session management
- Databases: Qdrant (vector database), Confluence integration
Core Capabilities:
- Multi-LLM Support: OpenAI, Groq, Ollama with configurable models and providers
- Document Processing: RAG (Retrieval-Augmented Generation) with parent document retriever
- Slack Bot: Intelligent routing with intent classification and LangGraph workflows
- New Relic Integration: Log analysis and investigation workflows
- MCP Tools: Brave Search, Kubernetes readonly, Context7, ChunkHound (code research)
langchain-playground/
├── src/
│ ├── api/ # REST API endpoints
│ │ ├── agent/ # Multi-agent investigation system
│ │ │ ├── domains/ # Domain agents (NewRelic, Sentry, AWS, Code Research)
│ │ │ ├── supervisor/ # Investigation supervisor
│ │ │ └── services/ # Investigation orchestration
│ │ ├── document/ # Document loading and querying (RAG)
│ │ ├── groq/ # Groq LLM provider endpoints
│ │ ├── health/ # Health check endpoints
│ │ ├── langgraph/ # LangGraph workflow endpoints
│ │ ├── ollama/ # Ollama local LLM endpoints
│ │ └── openai/ # OpenAI provider endpoints
│ ├── libraries/ # Core utilities and services
│ │ ├── aws/ # AWS SDK integrations (ECS, RDS, CloudWatch, OpenSearch)
│ │ ├── github/ # GitHub API and repository management
│ │ ├── langchain/ # LangChain utilities (LLM, embeddings, vector store)
│ │ ├── mcp/ # Model Context Protocol client
│ │ ├── newrelic/ # New Relic API integration
│ │ ├── sentry/ # Sentry API integration
│ │ ├── slack/ # Slack utilities
│ │ ├── logger.ts # Pino structured logging
│ │ └── redis.ts # Redis client configuration
│ ├── middlewares/ # Fastify middleware
│ ├── slack/ # Slack bot implementation
│ │ ├── event/ # Event handlers (app_mention, message)
│ │ │ ├── nodes/ # LangGraph nodes (intent classifier, summarizer, etc.)
│ │ │ └── stateGraph.ts # Main LangGraph state machine
│ │ └── index.ts # Slack app configuration
│ ├── index.ts # Main application entry point
│ ├── serverWithFastify.ts # REST API server
│ └── serverWithSlack.ts # Slack bot server
├── config/ # Configuration management
├── test/ # Test files and setup
├── docker-compose.yml # Development services (Redis, Qdrant, Unstructured API)
└── package.json # Dependencies and scripts
- Check everything:
npm run typecheck && npm run lint && npm test - Fix linting/formatting:
npm run lint:fix && npm run format:fix - Run all tests:
npm test(Jest with coverage) - Run single test:
npm test -- src/path/to/file.test.ts - Start development:
npm run dev(auto-reload with pretty logging) - Build for production:
npm run build(Rspack bundler) - Run production build:
npm start - Build and run Docker:
npm run docker:build && npm run docker:run
- API Server: http://localhost:8080 (Fastify mode)
- Slack Bot: Connects to Slack workspace (Slack mode)
- Redis: localhost:6379 (caching and sessions)
- Qdrant: http://localhost:6333 (vector database)
- Unstructured API: http://localhost:8082 (document processing)
- ChunkHound: http://localhost:8090 (code research MCP server)
- Services:
docker-compose up -d(starts Redis, Qdrant, Unstructured API, ChunkHound)
- TypeScript: Strict mode with
isolatedModules,noFallthroughCasesInSwitch,forceConsistentCasingInFileNames - Line Length: 150 characters maximum
- Indentation: 2 spaces (consistent across all files)
- Quotes: Single quotes preferred, double quotes for strings containing single quotes
- Semicolons: Required (enforced by ESLint)
- Trailing Commas: No trailing commas (trailingComma: 'none')
- Path Aliases: Always use
@/imports instead of relative paths - Import Organization: External → builtin → internal → sibling → parent (auto-sorted)
- Naming Conventions: Use "URL" (not "Url"), "API" (not "Api"), "ID" (not "Id")
- Type Safety: NEVER use
@ts-expect-erroror@ts-ignore- fix type issues properly - Functions: Prefer
constoverlet, use async/await, include explicit return types - Comments: Use JSDoc for complex logic; avoid redundant comments explaining obvious code
ESLint Rules:
- TypeScript recommended rules enabled
- Import order enforcement
- No restricted imports from
src/*(use path aliases) - Unused variables with
_prefix ignored - Test-specific relaxed rules for
*.test.ts
LLM Provider Management:
// Use centralized LLM getter functions
import { getChatOllama, getChatGroq, getChatOpenAI } from '@/libraries/langchain/llm';
const model = getChatOllama(temperature, logger);Document Processing (RAG):
// Parent document retriever pattern for better context
import { getParentDocumentRetriever } from '@/libraries/langchain/retrievers/parentDocument';
const retriever = await getParentDocumentRetriever(collectionName, logger);LangGraph Workflow Design:
// State annotation pattern for type safety
const graph = new StateGraph(OverallStateAnnotation)
.addNode('intent-classifier', intentClassifierNode)
.addNode('intent-router', intentRouterNode)
.addConditionalEdges('intent-router', routeToNextIntent)
.compile();Streaming Responses:
- Implement streaming for long-running operations
- Use proper error handling and cleanup
- Support both API and Slack response formats
Uses config npm package with environment-specific files:
- Structure:
config/default.json,config/custom-environment-variables.json - Server Modes:
fastify(REST API) orslack(Slack bot) - LLM Providers: Configure base URLs, API keys, models, temperatures
- External Services: Redis, Qdrant, Unstructured API, New Relic
- Environment Variables: Override any config value via environment variables
Environment Variables:
Create a .env file for local development (gitignored) with the following variables:
Refer @.env.dist for the full list of environment variables.
Minimal Setup:
For basic functionality, you only need:
# Core
NODE_ENV=development
SERVER_MODE=fastify
PORT=8080
# At least one LLM provider
OPENAI_API_KEY=your_openai_key
# Redis for caching
REDIS_URL=redis://localhost:6379
# Vector database
QDRANT_URL=http://localhost:6333ChunkHound Setup (Optional - Code Research):
To enable the Code Research agent with ChunkHound:
# Enable ChunkHound MCP server
CHUNKHOUND_ENABLED=true
CHUNKHOUND_URL=http://localhost:8090/mcp
# Optional: Auto-clone repositories for indexing
GITHUB_REPOSITORIES_ENABLED=true
GITHUB_REPOSITORIES_REPOS='[{"owner":"langchain-ai","repo":"langchainjs","branch":"main"}]'Note: ChunkHound requires Ollama with embedding and LLM models:
ollama pull mxbai-embed-large:latest
ollama pull llama3.1:8bAdding New Configuration:
When adding new configuration options, update all relevant places:
- Add to
config/default.jsonwith default values - Add to
config/custom-environment-variables.jsonfor environment variable mapping - Update TypeScript types if using typed config access
- Document in
README.mdand environment variable examples - Update Docker and deployment configurations as needed
All configuration keys MUST use consistent naming and be documented.
Multi-Agent Investigation:
POST /agent/investigate- Unified investigation endpoint using multi-agent supervisor- Automatically routes to appropriate domain agents (NewRelic, Sentry, AWS ECS/RDS, Code Research)
- Supports configurable LLM provider, model, and timeout options
Document Management (RAG):
DELETE /document/reset- Reset document storePUT /document/load/directory- Load documents from directoryPUT /document/load/confluence- Load from ConfluencePOST /document/query- Query documents with RAG
LLM Provider Endpoints:
POST /openai/thread- Create OpenAI conversation threadPOST /groq/thread- Create Groq conversation threadPOST /ollama/thread- Create Ollama conversation threadGET|POST /*/thread/:id- Get/continue specific thread
LangGraph Workflows:
POST /langgraph/thread- Create LangGraph workflow threadPOST /langgraph/newrelic/investigate- New Relic log analysis workflowPOST /langgraph/sentry/investigate- Sentry issue investigation workflow
Health & Monitoring:
GET /health- Health check endpoint
Architecture:
- LangGraph state machine for intelligent routing
- Intent classification → Tool execution → Response generation
- Multi-step workflows with state management
Key Nodes:
- Intent Classifier: Determines user intent from message
- Intent Router: Routes to appropriate processing node
- MCP Tools: Executes Model Context Protocol tools
- Summarize: Creates thread summaries
- Translate: Language translation
- Find Information: RAG-based information retrieval
- General Response: Fallback conversational responses
- Final Response: Formats and sends Slack message
Event Handling:
app_mention: Triggered when bot is mentionedmessage: Processes direct messages- Thread-aware responses with proper formatting
IMPORTANT: You need to run the test with network permission enabled.
- Framework: Jest with ts-jest preset and Node.js environment
- Test Files:
*.test.tsin__tests__/directories adjacent to source code - Test Names: Omit "should" from test descriptions (e.g.,
it("validates input")notit("should validate input")) - Mocking: Mock external dependencies appropriately, auto-clear mocks enabled
- Coverage: Enabled with json, lcov, and text-summary reporters
- Path Mapping: Uses same aliases as main code (
@/src/*, etc.) - Timeout: 10 seconds default with global setup and teardown
Test Structure Pattern:
Use describe blocks to group scenarios, beforeEach for setup, and a shared result variable:
import { beforeEach, describe, expect, it } from '@jest/globals';
import { myFunction } from '../myModule';
describe('myFunction', () => {
let result: unknown;
describe('with valid input', () => {
beforeEach(() => {
result = myFunction({ data: 'test' });
});
it('returns expected output', () => {
expect(result).toStrictEqual({ success: true, data: 'test' });
});
});
describe('with edge case', () => {
beforeEach(() => {
result = myFunction({});
});
it('handles empty input gracefully', () => {
expect(result).toStrictEqual({ success: true });
});
});
});Key Conventions:
- Imports: Import
beforeEach,describe,expect,itfrom@jest/globals(alphabetically sorted) - Shared Result: Declare
let result: unknown;at the top of eachdescribeblock - Setup in beforeEach: Perform all setup and function calls in
beforeEach - Single Assertion: Each
itblock should contain only assertions, not setup logic - Descriptive Describes: Use
describenames that explain the scenario (e.g., "with valid input", "when error occurs") - Prefer toStrictEqual: Use
toStrictEqualfor object comparisons to ensure exact matching
Test Commands:
npm test # Run all tests with coverage
npm test -- --watch # Watch mode for development
npm test -- src/path/to/file.test.ts # Run specific test file
npm test -- --coverage # Explicit coverage reportRequired Services (via Docker Compose):
- Redis: Caching and session storage (
localhost:6379) - Qdrant: Vector database for embeddings (
localhost:6333) - Unstructured API: Document processing (
localhost:8082)
Optional Services:
- Ollama: Local LLM inference (desktop installation recommended)
- New Relic: Log analysis and monitoring
- Confluence: Document source integration
- ChunkHound: Code research MCP server (requires Ollama for embeddings/LLM)
- Secrets Management: NEVER commit API keys, tokens, or secrets to repository
- Environment Variables: Use
.envfiles for local development (.envis gitignored) - Data Types: Use appropriate TypeScript types that limit exposure of sensitive information
- Input Validation: Validate all user inputs with Zod schemas on both client and server
- Rate Limiting: Configured in Fastify setup to prevent abuse
- CORS: Properly configured for API endpoints with specific origins
- HTTPS: Use HTTPS in production environments
- Dependencies: Regular
npm auditand dependency updates - Principle of Least Privilege: Grant minimum necessary permissions
- Logging: Structured logging with Pino; avoid logging sensitive data
- Content Security: Slack message validation and sanitization to prevent injection attacks
Before submitting changes, run:
npm run typecheck # TypeScript compilation check
npm run lint # ESLint with TypeScript rules
npm run format # Prettier formatting
npm test # Jest test suite
npm run build # Production build verificationAll checks must pass. Use npm run lint -- --fix and npm run format for auto-fixes.
- ALWAYS run quality checks:
npm run typecheck && npm run lint && npm testbefore committing - Fix issues automatically:
npm run lint -- --fix && npm run formatfor auto-fixable problems - Verify build passes:
npm run buildbefore pushing to ensure production build works - NEVER force push: Never use
git push --forceon main branch - Feature branches: Use
git push --force-with-leaseonly on feature branches if needed - Branch verification: Always verify current branch before any force operations
- Commit messages: Use conventional commit format (enforced by commitlint)
- Pre-commit hooks: Husky + lint-staged automatically format and lint on commit
- Focus: Keep PRs focused on a single feature or concern
- Description: Include clear description of changes and rationale
- Testing: Ensure all existing tests pass and add tests for new features
- Type Safety: Maintain strict TypeScript compliance
- Documentation: Update relevant documentation for API or architecture changes
- Performance: Consider impact on LLM token usage and response times
Error Handling:
try {
const result = await llmOperation();
logger.info({ result }, 'Operation completed');
return result;
} catch (error) {
logger.error({ error }, 'Operation failed');
throw error;
}Configuration Access:
import config from 'config';
const apiKey = config.get<string>('openai.apiKey');
const model = config.get<string>('openai.model');LangChain Chain Building:
import { RunnableSequence } from '@langchain/core/runnables';
const chain = RunnableSequence.from([prompt, model, outputParser]);
const result = await chain.invoke({ input });- Dual Mode: Supports both REST API and Slack bot modes via configuration
- Modular Design: Clear separation between API routes, libraries, and Slack logic
- Type Safety: Comprehensive TypeScript usage with strict compilation
- Scalability: Redis-based caching and session management
- Observability: Structured logging and health checks
- Extensibility: Plugin-based architecture for new LLM providers and tools
This project demonstrates production-ready patterns for building LLM-powered applications with modern TypeScript, comprehensive testing, and enterprise integrations.