Metadata-Version: 2.4
Name: ingenious
Version: 0.2.6
Summary: An enterprise-grade Python library for quickly setting up APIs to interact with AI Agents
Project-URL: Homepage, https://github.com/Insight-Services-APAC/ingenious
Project-URL: Documentation, https://insight-services-apac.github.io/ingenious/
Project-URL: Repository, https://github.com/Insight-Services-APAC/ingenious
Project-URL: Issues, https://github.com/Insight-Services-APAC/ingenious/issues
Author-email: John Rampono <john.rampono@insight.com>, Kokko Ng <kokko.ng@insight.com>, Elliot Zhu <elliot.zhu@insight.com>
License: MIT
License-File: LICENSE
Keywords: agent,autogen,azure,fastapi
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.13
Requires-Dist: aiofiles>=24.1.0
Requires-Dist: aiohttp==3.12.15
Requires-Dist: dependency-injector==4.48.1
Requires-Dist: fastapi==0.115.9
Requires-Dist: pydantic-settings>=2.10.1
Requires-Dist: pydantic==2.11.5
Requires-Dist: python-dotenv>=1.0.1
Requires-Dist: rich==13.7.1
Requires-Dist: structlog==25.4.0
Requires-Dist: typer==0.16.0
Requires-Dist: uvicorn>=0.35.0
Provides-Extra: ai
Requires-Dist: ats>=1.0.8; extra == 'ai'
Requires-Dist: autogen-agentchat>=0.5.7; extra == 'ai'
Requires-Dist: autogen-ext>=0.5.7; extra == 'ai'
Requires-Dist: openai>=1.82.0; extra == 'ai'
Requires-Dist: tiktoken>=0.9.0; extra == 'ai'
Provides-Extra: auth
Requires-Dist: bcrypt==4.3.0; extra == 'auth'
Requires-Dist: passlib>=1.7.4; extra == 'auth'
Requires-Dist: python-jose[cryptography]>=3.5.0; extra == 'auth'
Provides-Extra: azure
Requires-Dist: azure-core==1.34.0; extra == 'azure'
Requires-Dist: azure-cosmos>=4.9.0; extra == 'azure'
Requires-Dist: azure-identity>=1.17.1; extra == 'azure'
Requires-Dist: azure-keyvault-secrets>=4.10.0; extra == 'azure'
Requires-Dist: azure-search-documents>=11.5.2; extra == 'azure'
Requires-Dist: azure-storage-blob>=12.25.1; extra == 'azure'
Provides-Extra: azure-full
Requires-Dist: aiosqlite==0.21.0; extra == 'azure-full'
Requires-Dist: ats>=1.0.8; extra == 'azure-full'
Requires-Dist: autogen-agentchat>=0.5.7; extra == 'azure-full'
Requires-Dist: autogen-ext>=0.5.7; extra == 'azure-full'
Requires-Dist: azure-core==1.34.0; extra == 'azure-full'
Requires-Dist: azure-cosmos>=4.9.0; extra == 'azure-full'
Requires-Dist: azure-identity>=1.17.1; extra == 'azure-full'
Requires-Dist: azure-keyvault-secrets>=4.10.0; extra == 'azure-full'
Requires-Dist: azure-search-documents>=11.5.2; extra == 'azure-full'
Requires-Dist: azure-storage-blob>=12.25.1; extra == 'azure-full'
Requires-Dist: bcrypt==4.3.0; extra == 'azure-full'
Requires-Dist: chromadb>=1.0.11; extra == 'azure-full'
Requires-Dist: fastapi-cli==0.0.7; extra == 'azure-full'
Requires-Dist: flask>=3.1.1; extra == 'azure-full'
Requires-Dist: jinja2==3.1.6; extra == 'azure-full'
Requires-Dist: jsonpickle==4.1.1; extra == 'azure-full'
Requires-Dist: markdown>=3.8.2; extra == 'azure-full'
Requires-Dist: openai>=1.82.0; extra == 'azure-full'
Requires-Dist: pandas>=2.3.1; extra == 'azure-full'
Requires-Dist: passlib>=1.7.4; extra == 'azure-full'
Requires-Dist: psutil>=7.0.0; extra == 'azure-full'
Requires-Dist: pyodbc>=5.2.0; extra == 'azure-full'
Requires-Dist: python-jose[cryptography]>=3.5.0; extra == 'azure-full'
Requires-Dist: tiktoken>=0.9.0; extra == 'azure-full'
Provides-Extra: chunk
Requires-Dist: ijson==3.2.3; extra == 'chunk'
Requires-Dist: jsonlines==3.1.0; extra == 'chunk'
Requires-Dist: langchain-experimental==0.3.4; extra == 'chunk'
Requires-Dist: langchain-openai==0.3.0; extra == 'chunk'
Requires-Dist: langchain-text-splitters==0.3.0; extra == 'chunk'
Requires-Dist: regex==2024.11.6; extra == 'chunk'
Requires-Dist: xxhash==3.5.0; extra == 'chunk'
Provides-Extra: core
Requires-Dist: aiosqlite==0.21.0; extra == 'core'
Requires-Dist: fastapi-cli==0.0.7; extra == 'core'
Requires-Dist: jinja2==3.1.6; extra == 'core'
Requires-Dist: jsonpickle==4.1.1; extra == 'core'
Requires-Dist: markdown>=3.8.2; extra == 'core'
Requires-Dist: pandas>=2.3.1; extra == 'core'
Provides-Extra: database
Requires-Dist: psutil>=7.0.0; extra == 'database'
Requires-Dist: pyodbc>=5.2.0; extra == 'database'
Provides-Extra: dataprep
Requires-Dist: backoff==2.2.0; extra == 'dataprep'
Requires-Dist: scrapfly-sdk==0.8.23; extra == 'dataprep'
Provides-Extra: development
Requires-Dist: ipython==9.2.0; extra == 'development'
Provides-Extra: docs
Requires-Dist: mkdocs-git-revision-date-localized-plugin>=1.4.7; extra == 'docs'
Requires-Dist: mkdocs-minify-plugin>=0.8.0; extra == 'docs'
Requires-Dist: mkdocs-nav-weight>=0.2.0; extra == 'docs'
Requires-Dist: mkdocs-redirects>=1.2.2; extra == 'docs'
Requires-Dist: mkdocs-table-reader-plugin>=3.1.0; extra == 'docs'
Provides-Extra: document-advanced
Requires-Dist: pdfminer-six==20250506; extra == 'document-advanced'
Requires-Dist: unstructured[all-docs]==0.17.2; extra == 'document-advanced'
Provides-Extra: document-processing
Requires-Dist: azure-ai-documentintelligence==1.0.2; extra == 'document-processing'
Requires-Dist: pymupdf==1.26.1; extra == 'document-processing'
Provides-Extra: full
Requires-Dist: aiosqlite==0.21.0; extra == 'full'
Requires-Dist: ats>=1.0.8; extra == 'full'
Requires-Dist: autogen-agentchat>=0.5.7; extra == 'full'
Requires-Dist: autogen-ext>=0.5.7; extra == 'full'
Requires-Dist: azure-ai-documentintelligence==1.0.2; extra == 'full'
Requires-Dist: azure-core==1.34.0; extra == 'full'
Requires-Dist: azure-cosmos>=4.9.0; extra == 'full'
Requires-Dist: azure-identity>=1.17.1; extra == 'full'
Requires-Dist: azure-keyvault-secrets>=4.10.0; extra == 'full'
Requires-Dist: azure-search-documents>=11.5.2; extra == 'full'
Requires-Dist: azure-storage-blob>=12.25.1; extra == 'full'
Requires-Dist: backoff==2.2.0; extra == 'full'
Requires-Dist: bcrypt==4.3.0; extra == 'full'
Requires-Dist: chromadb>=1.0.11; extra == 'full'
Requires-Dist: fastapi-cli==0.0.7; extra == 'full'
Requires-Dist: flask>=3.1.1; extra == 'full'
Requires-Dist: jinja2==3.1.6; extra == 'full'
Requires-Dist: jsonpickle==4.1.1; extra == 'full'
Requires-Dist: markdown>=3.8.2; extra == 'full'
Requires-Dist: matplotlib==3.10.3; extra == 'full'
Requires-Dist: openai>=1.82.0; extra == 'full'
Requires-Dist: pandas>=2.3.1; extra == 'full'
Requires-Dist: passlib>=1.7.4; extra == 'full'
Requires-Dist: psutil>=7.0.0; extra == 'full'
Requires-Dist: pymupdf==1.26.1; extra == 'full'
Requires-Dist: pyodbc>=5.2.0; extra == 'full'
Requires-Dist: python-jose[cryptography]>=3.5.0; extra == 'full'
Requires-Dist: scrapfly-sdk==0.8.23; extra == 'full'
Requires-Dist: seaborn==0.13.2; extra == 'full'
Requires-Dist: sentence-transformers==5.0.0; extra == 'full'
Requires-Dist: tiktoken>=0.9.0; extra == 'full'
Provides-Extra: knowledge-base
Requires-Dist: chromadb>=1.0.11; extra == 'knowledge-base'
Provides-Extra: knowledge-focused
Requires-Dist: aiosqlite==0.21.0; extra == 'knowledge-focused'
Requires-Dist: ats>=1.0.8; extra == 'knowledge-focused'
Requires-Dist: autogen-agentchat>=0.5.7; extra == 'knowledge-focused'
Requires-Dist: autogen-ext>=0.5.7; extra == 'knowledge-focused'
Requires-Dist: chromadb>=1.0.11; extra == 'knowledge-focused'
Requires-Dist: fastapi-cli==0.0.7; extra == 'knowledge-focused'
Requires-Dist: jinja2==3.1.6; extra == 'knowledge-focused'
Requires-Dist: jsonpickle==4.1.1; extra == 'knowledge-focused'
Requires-Dist: markdown>=3.8.2; extra == 'knowledge-focused'
Requires-Dist: openai>=1.82.0; extra == 'knowledge-focused'
Requires-Dist: pandas>=2.3.1; extra == 'knowledge-focused'
Requires-Dist: sentence-transformers==5.0.0; extra == 'knowledge-focused'
Requires-Dist: tiktoken>=0.9.0; extra == 'knowledge-focused'
Provides-Extra: minimal
Provides-Extra: ml
Requires-Dist: sentence-transformers==5.0.0; extra == 'ml'
Provides-Extra: standard
Requires-Dist: aiosqlite==0.21.0; extra == 'standard'
Requires-Dist: ats>=1.0.8; extra == 'standard'
Requires-Dist: autogen-agentchat>=0.5.7; extra == 'standard'
Requires-Dist: autogen-ext>=0.5.7; extra == 'standard'
Requires-Dist: bcrypt==4.3.0; extra == 'standard'
Requires-Dist: fastapi-cli==0.0.7; extra == 'standard'
Requires-Dist: jinja2==3.1.6; extra == 'standard'
Requires-Dist: jsonpickle==4.1.1; extra == 'standard'
Requires-Dist: markdown>=3.8.2; extra == 'standard'
Requires-Dist: openai>=1.82.0; extra == 'standard'
Requires-Dist: pandas>=2.3.1; extra == 'standard'
Requires-Dist: passlib>=1.7.4; extra == 'standard'
Requires-Dist: psutil>=7.0.0; extra == 'standard'
Requires-Dist: pyodbc>=5.2.0; extra == 'standard'
Requires-Dist: python-jose[cryptography]>=3.5.0; extra == 'standard'
Requires-Dist: tiktoken>=0.9.0; extra == 'standard'
Provides-Extra: test
Requires-Dist: httpx==0.28.1; extra == 'test'
Requires-Dist: hypothesis==6.136.2; extra == 'test'
Requires-Dist: mypy==1.16.1; extra == 'test'
Requires-Dist: pip-audit==2.9.0; extra == 'test'
Requires-Dist: pre-commit==4.2.0; extra == 'test'
Requires-Dist: pytest-asyncio==0.26.0; extra == 'test'
Requires-Dist: pytest-cov==6.1.1; extra == 'test'
Requires-Dist: pytest-mock==3.14.0; extra == 'test'
Requires-Dist: pytest-timeout==2.4.0; extra == 'test'
Requires-Dist: pytest==8.3.5; extra == 'test'
Requires-Dist: reportlab==4.4.2; extra == 'test'
Requires-Dist: ruff==0.11.10; extra == 'test'
Requires-Dist: twine==6.0.0; extra == 'test'
Requires-Dist: types-markdown==3.8.0.20250708; extra == 'test'
Requires-Dist: types-psutil==7.0.0.20250601; extra == 'test'
Requires-Dist: types-pyyaml==6.0.12.20250516; extra == 'test'
Requires-Dist: types-requests==2.32.4.20250611; extra == 'test'
Requires-Dist: vulture==2.14; extra == 'test'
Provides-Extra: ui
Requires-Dist: flask>=3.1.1; extra == 'ui'
Provides-Extra: visualization
Requires-Dist: matplotlib==3.10.3; extra == 'visualization'
Requires-Dist: seaborn==0.13.2; extra == 'visualization'
Description-Content-Type: text/markdown

# Insight Ingenious

[![Version](https://img.shields.io/badge/version-0.2.5-blue.svg)](https://github.com/Insight-Services-APAC/ingenious)
[![Python](https://img.shields.io/badge/python-3.13+-green.svg)](https://www.python.org/downloads/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Insight-Services-APAC/ingenious)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![License](https://img.shields.io/badge/license-MIT-purple.svg)](LICENSE)

Ingenious is a tool for quickly setting up APIs to interact with AI Agents. It features multi-agent conversation flows using Microsoft's AutoGen, JWT authentication, and supports both local development (SQLite, ChromaDB) and production Azure deployments (Azure SQL, Cosmos DB, Azure AI Search, Azure Blob, Container Apps).

## Quick Start

Get up and running in 5 minutes with just an Azure OpenAI API key!

### Prerequisites
- Python 3.13 or higher (required - earlier versions are not supported)
- OpenAI or Azure OpenAI API credentials
- [uv package manager](https://docs.astral.sh/uv/)

**Flexible Architecture**: Ingenious supports both local development (SQLite, ChromaDB) and production Azure deployments (Azure SQL, Cosmos DB, Azure AI Search, Azure Blob, Container Apps). Start local, scale to Azure as needed.

### AI-Assisted Set Up (give this prompt to your preferred coding agent)

**WARNING: Audit ALL Azure CLI commands!**

```markdown
Follow all steps in [this guide](https://blog.insight-services-apac.dev/ingenious/getting-started/) and [this guide](https://blog.insight-services-apac.dev/ingenious/guides/complete-azure-deployment/).

Set up ingenious locally first and then migrate to Azure services as shown in the docs.

- Deploy only required resources at minimal cost.
- Use a new resource group: **<your-new-rg-name>**.
- For the SQL Server SKU choose Basic - 5 DTUs
- Azure CLI access is available.
```
### 5-Minute Setup

1. **Install and Initialize**:
    ```bash
    # Navigate to your desired project directory first
    cd /path/to/your/project

    # Set up the uv project
    uv init

    # Choose installation based on features needed:

    # Basic API server only (33 packages)
    uv add "ingenious"

    # Standard production setup with auth + AI + database (86 packages)
    uv add "ingenious[standard]"

    # Full Azure cloud integration (recommended for production)
    uv add "ingenious[azure-full]"

    # Everything including document processing and ML
    uv add "ingenious[full]"

    # Or build your own combination:
    # uv add "ingenious[core,auth,ai]"           # Basic AI workflows with auth
    # uv add "ingenious[ai,knowledge-base]"      # AI + vector search only
    # uv add "ingenious[azure,database]"         # Azure + database without AI

    # For nightly builds, add --index-url prefix:
    # uv add --index-url https://test.pypi.org/simple/ "ingenious[azure-full]"

    # Initialize project in the current directory
    uv run ingen init
    ```

2. **Configure Credentials**:
    Create a `.env` file with your Azure OpenAI credentials:
    ```bash
    # Create .env file in current directory
    touch .env

    # Edit .env file with your actual credentials
    ```

    **Required configuration (add to .env file)**:
    ```bash
    # Core AI Model Configuration (REQUIRED)
    INGENIOUS_MODELS__0__MODEL=gpt-4o-mini
    INGENIOUS_MODELS__0__API_TYPE=rest
    INGENIOUS_MODELS__0__API_VERSION=2024-12-01-preview
    INGENIOUS_MODELS__0__DEPLOYMENT=gpt-4o-mini-deployment
    INGENIOUS_MODELS__0__API_KEY=your-actual-api-key-here
    INGENIOUS_MODELS__0__BASE_URL=https://eastus.api.cognitive.microsoft.com/

    # For Azure OpenAI: Use the Cognitive Services endpoint format (not OpenAI endpoint)
    # CORRECT: https://eastus.api.cognitive.microsoft.com/
    # INCORRECT: https://your-resource.openai.azure.com/
    # For OpenAI (not Azure), use:
    # INGENIOUS_MODELS__0__BASE_URL=https://api.openai.com/v1
    # INGENIOUS_MODELS__0__API_VERSION=2024-02-01

    # Web Server Configuration (use different port if 80 conflicts)
    INGENIOUS_WEB_CONFIGURATION__PORT=8000
    INGENIOUS_WEB_CONFIGURATION__IP_ADDRESS=0.0.0.0
    INGENIOUS_WEB_CONFIGURATION__AUTHENTICATION__ENABLE=false

    # Chat Service Configuration (REQUIRED)
    INGENIOUS_CHAT_SERVICE__TYPE=multi_agent

    # Production: Disable built-in workflows (optional)
    # INGENIOUS_CHAT_SERVICE__ENABLE_BUILTIN_WORKFLOWS=false

    # Chat History Database (Local SQLite)
    INGENIOUS_CHAT_HISTORY__DATABASE_TYPE=sqlite
    INGENIOUS_CHAT_HISTORY__DATABASE_PATH=./.tmp/chat_history.db
    INGENIOUS_CHAT_HISTORY__MEMORY_PATH=./.tmp

    # Knowledge base configuration - local ChromaDB for development
    KB_POLICY=local_only
    KB_TOPK_DIRECT=3
    KB_TOPK_ASSIST=5
    KB_MODE=direct

    # SQL database configuration - local SQLite for development
    INGENIOUS_LOCAL_SQL_DB__DATABASE_PATH=./.tmp/sample_sql.db

    # Logging Configuration
    INGENIOUS_LOGGING__ROOT_LOG_LEVEL=info
    INGENIOUS_LOGGING__LOG_LEVEL=info
    ```

3. **Validate Configuration**:
    ```bash
    uv run ingen validate  # Check configuration before starting
    ```

    **Expected validation output**: You should see confirmation that your configuration is valid and a count of available workflows:
    - **Minimal install**: 0/3 workflows (requires `[ai]` group for workflow functionality)
    - **Standard install**: 3/4 workflows (classification-agent, sql-manipulation-agent working; knowledge-base-agent requires `[knowledge-base]` group)
    - **Azure-full install**: 4/4 workflows working (classification-agent, knowledge-base-agent, sql-manipulation-agent, and bike-insights after `ingen init`)

    **If validation fails with port conflicts**:
    ```bash
    # Find and kill process using port 8000 (recommended approach)
    lsof -ti:8000 | xargs kill -9
    uv run ingen validate

    # Alternative: Check if validation passes with different port
    INGENIOUS_WEB_CONFIGURATION__PORT=8001 uv run ingen validate

    # Or update your .env file before validating:
    echo "INGENIOUS_WEB_CONFIGURATION__PORT=8001" >> .env
    uv run ingen validate
    ```

    > **⚠️ BREAKING CHANGE**: Ingenious now uses **pydantic-settings** for configuration via environment variables. Legacy YAML configuration files (`config.yml`, `profiles.yml`) are **no longer supported** and must be migrated to environment variables with `INGENIOUS_` prefixes. Use the migration script:
    > ```bash
    > uv run python scripts/migrate_config.py --yaml-file config.yml --output .env
    > uv run python scripts/migrate_config.py --yaml-file profiles.yml --output .env.profiles
    > ```

4. **Start the Server**:
    ```bash
    # REQUIRED: Use KB_POLICY=local_only for knowledge-base-agent to work with ChromaDB
    KB_POLICY=local_only uv run ingen serve --port 8000

    # Alternative: Start server without KB prefix (but knowledge-base-agent may not work)
    uv run ingen serve --port 8000

    # Note: Default port is 80, but port 8000 is recommended to avoid conflicts
    # Additional options:
    # --host 0.0.0.0         # Bind host (default: 0.0.0.0)
    # --port                 # Port to bind (default: 80 or $INGENIOUS_WEB_CONFIGURATION__PORT)
    ```

5. **Verify Health**:
    ```bash
    # Check server health (adjust port if different)
    curl http://localhost:8000/api/v1/health
    ```

    **Expected health response**: A JSON response indicating server status:
    ```json
    {
      "status": "healthy",
      "timestamp": "2025-08-29T01:15:30.830525",
      "response_time_ms": 1.4,
      "components": {"configuration": "ok", "profile": "ok"},
      "version": "1.0.0",
      "uptime": "available"
    }
    ```

6. **Test with Core Workflows**:

    Create test files to avoid JSON escaping issues:
    ```bash
    # Create test files for each workflow
    echo '{"user_prompt": "Analyze this customer feedback: Great product", "conversation_flow": "classification-agent"}' > test_classification.json
    echo '{"user_prompt": "Search for documentation about setup", "conversation_flow": "knowledge-base-agent"}' > test_knowledge.json
    echo '{"user_prompt": "Show me all tables in the database", "conversation_flow": "sql-manipulation-agent"}' > test_sql.json

    # Test each workflow
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_classification.json
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_knowledge.json
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_sql.json
    ```

    **To populate knowledge base for testing** (optional but recommended):
    ```bash
    # Create sample knowledge base document for testing
    mkdir -p .tmp/knowledge_base
    cat > .tmp/knowledge_base/setup_guide.md << 'EOF'
    # Ingenious Setup Guide

    ## Quick Setup Instructions

    Ingenious is a multi-agent AI framework that allows you to quickly set up APIs for AI agents.

    ### Prerequisites
    - Python 3.13+
    - OpenAI API key or Azure OpenAI credentials
    - UV package manager

    ### Installation Steps
    1. Initialize UV project: `uv init`
    2. Install Ingenious: `uv add "ingenious[azure-full]"`
    3. Initialize project: `uv run ingen init`
    4. Configure environment variables in .env file
    5. Start server: `uv run ingen serve --port 8000`
    EOF

    # Now test knowledge-base-agent again to see populated results
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_knowledge.json
    ```

**Expected Responses**:
- **Successful classification-agent response**: JSON with message analysis, sentiment scores, and topic categorization
- **Successful knowledge-base-agent response**: JSON with relevant information retrieved from local ChromaDB (with sample document, will contain setup instructions; without, may indicate empty knowledge base)
- **Successful sql-manipulation-agent response**: JSON with SQL query results showing database table information from local SQLite database (sample database includes `students_performance` table)

**Example successful responses**:
```bash
# classification-agent typical response format:
{"response": "Analysis: Positive sentiment (0.8/1.0)... Category: Product Feedback"}

# knowledge-base-agent with populated knowledge base:
{"response": "Based on the setup guide: Ingenious requires Python 3.13+..."}

# sql-manipulation-agent typical response:
{"response": "Found 3 tables in database: users, products, orders..."}
```

That's it! You should see a JSON response with AI analysis of the input.

**Next Steps - Test Additional Workflows**:

7. **Test bike-insights Workflow (Requires `ingen init` first)**:

    The `bike-insights` workflow is part of the project template and must be initialized first:
    ```bash
    # First initialize project to get bike-insights workflow
    uv run ingen init

    # Create bike-insights test data file
    # IMPORTANT: bike-insights requires JSON data in the user_prompt field (double-encoded JSON)
    printf '%s\n' '{
      "user_prompt": "{\"revision_id\": \"test-v1\", \"identifier\": \"test-001\", \"stores\": [{\"name\": \"Test Store\", \"location\": \"NSW\", \"bike_sales\": [{\"product_code\": \"MB-TREK-2021-XC\", \"quantity_sold\": 2, \"sale_date\": \"2023-04-01\", \"year\": 2023, \"month\": \"April\", \"customer_review\": {\"rating\": 4.5, \"comment\": \"Great bike\"}}], \"bike_stock\": []}]}",
      "conversation_flow": "bike-insights"
    }' > test_bike_insights.json

    # Test bike-insights workflow
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_bike_insights.json
    ```

    **Expected bike-insights response**: JSON with comprehensive bike sales analysis from multiple agents (fiscal analysis, customer sentiment, summary, and bike lookup).

**Important Notes**:
- **Core Library Workflows** (`classification-agent`, `knowledge-base-agent`, `sql-manipulation-agent`) are available by default and accept simple text prompts
- **Template Workflows** like `bike-insights` require JSON-formatted data with specific fields and are only available after running `ingen init`
- The `bike-insights` workflow is the recommended "Hello World" example for new users
- **Production Security**: Set `INGENIOUS_CHAT_SERVICE__ENABLE_BUILTIN_WORKFLOWS=false` to disable built-in workflows and expose only your custom `ingenious_extensions` workflows

## Next Steps: Creating Custom Workflows

Once you have the basic setup working with the core workflows, you can create your own custom conversation flows:

**[Create Custom Workflows →](docs/guides/custom-workflows.md)**

Learn how to:
- Build custom AI agents for your specific use cases
- Implement multi-agent conversation patterns
- Handle complex business logic and data processing
- Deploy and test your custom workflows

## Documentation

For detailed documentation, see the [docs](https://insight-services-apac.github.io/ingenious/).

## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](https://github.com/Insight-Services-APAC/ingenious/blob/main/CONTRIBUTING.md) for guidelines.

## License

This project is licensed under the terms specified in the [LICENSE](https://github.com/Insight-Services-APAC/ingenious/blob/main/LICENSE) file.
