├── .github └── workflows │ ├── ci.yaml │ ├── helm-release.yaml │ └── python-publish.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── demo ├── .coveragerc ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── Makefile ├── README.md ├── agents │ ├── __init__.py │ ├── audit │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── config.py │ │ ├── main.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ └── test_agent.py │ │ ├── types.py │ │ └── utils.py │ ├── billing │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── api_main.py │ │ ├── config.py │ │ ├── dspy_modules │ │ │ ├── __init__.py │ │ │ ├── billing.py │ │ │ ├── billing_data.py │ │ │ ├── billing_dataset.py │ │ │ ├── billing_optimizer.py │ │ │ ├── billing_optimizer_simba.py │ │ │ ├── evaluation │ │ │ │ ├── __init__.py │ │ │ │ ├── metrics.py │ │ │ │ └── report.py │ │ │ └── optimized_billing_simba.json │ │ ├── main.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ ├── test_agent.py │ │ │ ├── test_agent_additional.py │ │ │ ├── test_api_main.py │ │ │ ├── test_billing_data.py │ │ │ ├── test_billing_dataset.py │ │ │ ├── test_billing_module.py │ │ │ ├── test_evaluation.py │ │ │ ├── test_evaluation_metrics.py │ │ │ ├── test_lazy_initialization.py │ │ │ ├── test_main_integration.py │ │ │ ├── test_module.py │ │ │ ├── test_module_fixed.py │ │ │ ├── test_module_simple.py │ │ │ ├── test_utils_coverage.py │ │ │ └── utils.py │ │ ├── types.py │ │ └── utils.py │ ├── claims │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── api_main.py │ │ ├── config.py │ │ ├── dspy_modules │ │ │ ├── __init__.py │ │ │ ├── claims.py │ │ │ ├── claims_data.py │ │ │ ├── claims_dataset.py │ │ │ ├── claims_errors.py │ │ │ ├── claims_optimizer.py │ │ │ ├── claims_optimizer_simba.py │ │ │ ├── claims_validators.py │ │ │ ├── optimized_claims.json │ │ │ └── optimized_claims_simba.json │ │ ├── main.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ ├── test_agent.py │ │ │ ├── test_agent_additional.py │ │ │ ├── test_api_main.py │ │ │ ├── test_claims_data.py │ │ │ ├── test_claims_dataset.py │ │ │ ├── test_claims_module.py │ │ │ └── test_main_integration.py │ │ └── types.py │ ├── escalation │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── config.py │ │ ├── dspy_modules │ │ │ ├── __init__.py │ │ │ └── escalation.py │ │ ├── main.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ ├── test_agent.py │ │ │ ├── test_agent_additional.py │ │ │ ├── test_escalation_data.py │ │ │ └── test_escalation_module.py │ │ └── types.py │ ├── frontend │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── config.py │ │ ├── guardrails.py │ │ ├── main.py │ │ ├── public │ │ │ ├── admin.html │ │ │ └── index.html │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ ├── test_agent.py │ │ │ ├── test_config_guardrails.py │ │ │ ├── test_main.py │ │ │ └── test_main_endpoint.py │ │ ├── types.py │ │ └── websocket_manager.py │ ├── policies │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent │ │ │ ├── __init__.py │ │ │ ├── agent.py │ │ │ ├── api │ │ │ │ ├── __init__.py │ │ │ │ ├── dependencies.py │ │ │ │ ├── middleware.py │ │ │ │ ├── models.py │ │ │ │ ├── routes.py │ │ │ │ └── validators.py │ │ │ ├── config.py │ │ │ ├── main.py │ │ │ ├── optimization │ │ │ │ ├── __init__.py │ │ │ │ ├── optimized_policies_simba.json │ │ │ │ ├── policies_dataset.py │ │ │ │ └── policies_optimizer_simba.py │ │ │ ├── reasoning.py │ │ │ ├── services │ │ │ │ ├── __init__.py │ │ │ │ ├── document_service.py │ │ │ │ ├── embeddings.py │ │ │ │ ├── reindex_service.py │ │ │ │ └── search_service.py │ │ │ ├── tests │ │ │ │ ├── test_policy_data.py │ │ │ │ └── test_routes.py │ │ │ ├── tools │ │ │ │ ├── __init__.py │ │ │ │ ├── database │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── example_data.py │ │ │ │ │ └── policy_data.py │ │ │ │ └── retrieval │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── full_document_retrieval.py │ │ │ │ │ └── policy_search.py │ │ │ ├── types.py │ │ │ └── utils │ │ │ │ ├── __init__.py │ │ │ │ └── async_helpers.py │ │ ├── ingestion │ │ │ ├── __init__.py │ │ │ ├── config.py │ │ │ ├── documents │ │ │ │ ├── auto.md │ │ │ │ ├── health.md │ │ │ │ ├── home.md │ │ │ │ └── life.md │ │ │ ├── minio_client.py │ │ │ ├── start_worker.py │ │ │ ├── temporal_client.py │ │ │ └── workflows │ │ │ │ ├── __init__.py │ │ │ │ ├── activities │ │ │ │ ├── __init__.py │ │ │ │ ├── document_chunking_activity.py │ │ │ │ ├── document_indexing_activity.py │ │ │ │ ├── document_loading_activity.py │ │ │ │ ├── document_verification_activity.py │ │ │ │ └── minio_activities.py │ │ │ │ ├── ingestion_workflow.py │ │ │ │ ├── minio_watcher_workflow.py │ │ │ │ └── worker.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ ├── retrieval_performance │ │ │ │ ├── __init__.py │ │ │ │ ├── api_client.py │ │ │ │ ├── context_metrics.py │ │ │ │ ├── data_utilities.py │ │ │ │ ├── evaluator.py │ │ │ │ ├── filtered_qa_pairs.json │ │ │ │ ├── llm_judge.py │ │ │ │ ├── metrics_config.py │ │ │ │ ├── mlflow_reporter.py │ │ │ │ ├── models.py │ │ │ │ └── performance_calculator.py │ │ │ ├── test_agent.py │ │ │ ├── test_api_integration.py │ │ │ ├── test_config.py │ │ │ ├── test_embeddings.py │ │ │ ├── test_reasoning.py │ │ │ ├── test_retrieval_performance.py │ │ │ ├── test_services.py │ │ │ ├── test_start_worker_integration.py │ │ │ ├── test_tools.py │ │ │ ├── test_validators.py │ │ │ └── test_vespa_deployment.py │ │ └── vespa │ │ │ ├── __init__.py │ │ │ ├── deploy_package.py │ │ │ ├── drop_index.py │ │ │ └── generate_package.py │ └── triage │ │ ├── Makefile │ │ ├── README.md │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── attention_net │ │ ├── __init__.py │ │ ├── attention_based_classifier.py │ │ ├── attention_net_trainer.py │ │ ├── classifier_v5.py │ │ └── config.py │ │ ├── baseline_model │ │ ├── __init__.py │ │ ├── classifier_v3.py │ │ ├── config.py │ │ ├── few_shots_classifier.py │ │ ├── fewshot_trainer.py │ │ ├── metrics.py │ │ └── utils.py │ │ ├── classifier_v6 │ │ ├── README.md │ │ ├── __init__.py │ │ ├── classifier_v6.py │ │ ├── data_utils.py │ │ ├── finetune_trainer.py │ │ ├── model_utils.py │ │ └── training_utils.py │ │ ├── classifier_v7 │ │ ├── README.md │ │ ├── __init__.py │ │ ├── classifier_v7.py │ │ ├── config.py │ │ ├── device_utils.py │ │ ├── finetune_trainer.py │ │ ├── gemma3_seq_cls.py │ │ ├── serve_classifier.py │ │ └── training_utils.py │ │ ├── classifier_v8 │ │ ├── README.md │ │ ├── __init__.py │ │ ├── classifier_v8.py │ │ ├── config.py │ │ ├── finetune_trainer.py │ │ └── training_utils.py │ │ ├── config.py │ │ ├── data_sets │ │ ├── bitext │ │ │ ├── triage-test-dataset.csv │ │ │ └── triage-train-dataset.csv │ │ ├── loader.py │ │ ├── synthetic │ │ │ ├── .env.example │ │ │ ├── Dockerfile │ │ │ ├── Makefile │ │ │ ├── WINDOWS_DEV.md │ │ │ ├── artifacts │ │ │ │ ├── triage-testing.jsonl │ │ │ │ └── triage-training.jsonl │ │ │ ├── dev_generator.py │ │ │ ├── dev_webserver.py │ │ │ ├── docker-compose.yml │ │ │ ├── src │ │ │ │ ├── triage_agent_dataset │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── __main__.py │ │ │ │ │ ├── config.py │ │ │ │ │ ├── constants.py │ │ │ │ │ ├── dataset_generator.py │ │ │ │ │ └── models.py │ │ │ │ └── triage_webserver │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── __main__.py │ │ │ │ │ ├── app.py │ │ │ │ │ ├── config.py │ │ │ │ │ ├── database │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base.py │ │ │ │ │ └── connection.py │ │ │ │ │ ├── models │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── data_models.py │ │ │ │ │ ├── routes │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── datasets.py │ │ │ │ │ └── examples.py │ │ │ │ │ ├── schemas │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── dataset_schemas.py │ │ │ │ │ └── example_schemas.py │ │ │ │ │ ├── services │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── dataset_service.py │ │ │ │ │ ├── static │ │ │ │ │ ├── img │ │ │ │ │ │ └── eggai-logo.svg │ │ │ │ │ └── js │ │ │ │ │ │ ├── datasets.js │ │ │ │ │ │ └── main.js │ │ │ │ │ └── templates │ │ │ │ │ ├── create_dataset.html │ │ │ │ │ ├── dataset_detail.html │ │ │ │ │ ├── datasets.html │ │ │ │ │ ├── edit_example.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── layout.html │ │ │ └── triage_viewer.html │ │ ├── triage-testing-proofread.jsonl │ │ ├── triage-testing.jsonl │ │ ├── triage-training-proofread.jsonl │ │ └── triage-training.jsonl │ │ ├── dspy_modules │ │ ├── __init__.py │ │ ├── classifier_v0.py │ │ ├── classifier_v1.py │ │ ├── classifier_v2 │ │ │ ├── __init__.py │ │ │ ├── classifier_v2.py │ │ │ ├── classifier_v2_optimizer.py │ │ │ └── optimizations_v2.json │ │ ├── classifier_v4 │ │ │ ├── __init__.py │ │ │ ├── classifier_v4.py │ │ │ ├── classifier_v4_optimizer.py │ │ │ └── optimizations_v4.json │ │ ├── evaluation │ │ │ ├── __init__.py │ │ │ ├── evaluate.py │ │ │ └── report.py │ │ └── small_talk.py │ │ ├── main.py │ │ ├── model_checkpoints │ │ ├── attention_net.pth │ │ └── fewshot_baseline_n_all.pkl │ │ ├── models.py │ │ ├── notebooks │ │ ├── exploratory_data_analysis.ipynb │ │ └── posthoc_model_analysis.ipynb │ │ ├── shared │ │ ├── __init__.py │ │ └── data_utils.py │ │ └── tests │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── run_classifier_tests.py │ │ ├── test_agent.py │ │ ├── test_agent_additional.py │ │ ├── test_agent_utils.py │ │ ├── test_classifier_comparison.py │ │ ├── test_classifier_v0.py │ │ ├── test_classifier_v1.py │ │ ├── test_classifier_v2.py │ │ ├── test_classifier_v3.py │ │ ├── test_classifier_v4.py │ │ ├── test_classifier_v5.py │ │ ├── test_classifier_v6.py │ │ ├── test_classifier_v6_evaluation.py │ │ ├── test_classifier_v7.py │ │ ├── test_classifier_v7_evaluation.py │ │ ├── test_classifier_v8.py │ │ ├── test_serve_classifier.py │ │ ├── test_shared_data_utils.py │ │ ├── test_small_talk.py │ │ └── test_utils.py ├── conftest.py ├── dev-requirements.txt ├── docker-compose-lmstudio.yaml ├── docker-compose-mlflow.yml ├── docker-compose.yml ├── dockerConfig │ ├── development-sql.yaml │ ├── grafana-dashboard.json │ ├── grafana-datasources.yaml │ ├── grafana-provisioning.yaml │ ├── loki.yaml │ ├── otel-collector.yaml │ ├── prometheus.yaml │ └── tempo.yaml ├── docs │ ├── advanced-topics │ │ ├── agent-optimization.md │ │ └── multi-environment-deployment.md │ ├── agentic-rag.md │ ├── agents-overview.md │ ├── building-agents-eggai.md │ ├── ingestion-pipeline.md │ ├── multi-agent-communication.md │ ├── retrieval-performance-testing.md │ ├── system-architecture.md │ └── vespa-search-guide.md ├── helm │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ │ ├── _helpers.tpl │ │ ├── deployments.yaml │ │ ├── monitoring.yaml │ │ ├── service.yaml │ │ └── tests │ │ │ └── test-connection.yaml │ └── values.yaml ├── libraries │ ├── README.md │ ├── __init__.py │ ├── communication │ │ ├── __init__.py │ │ ├── channels.py │ │ ├── messaging.py │ │ ├── protocol │ │ │ ├── README.md │ │ │ ├── __init__.py │ │ │ ├── enums.py │ │ │ └── messages.py │ │ └── transport.py │ ├── core │ │ ├── __init__.py │ │ ├── config.py │ │ ├── models.py │ │ └── patches.py │ ├── integrations │ │ ├── __init__.py │ │ └── vespa │ │ │ ├── __init__.py │ │ │ ├── config.py │ │ │ ├── schemas.py │ │ │ └── vespa_client.py │ ├── ml │ │ ├── __init__.py │ │ ├── device.py │ │ ├── dspy │ │ │ ├── __init__.py │ │ │ ├── language_model.py │ │ │ └── optimizer.py │ │ └── mlflow.py │ ├── observability │ │ ├── __init__.py │ │ ├── logger │ │ │ ├── __init__.py │ │ │ ├── config.py │ │ │ └── logger.py │ │ └── tracing │ │ │ ├── __init__.py │ │ │ ├── config.py │ │ │ ├── dspy.py │ │ │ ├── init_metrics.py │ │ │ ├── otel.py │ │ │ ├── pricing.py │ │ │ └── schemas.py │ └── testing │ │ ├── __init__.py │ │ ├── tests │ │ ├── __init__.py │ │ ├── test_channels.py │ │ ├── test_dspy_set_language_model.py │ │ ├── test_init_metrics.py │ │ ├── test_logger.py │ │ ├── test_otel.py │ │ └── test_pricing.py │ │ └── utils │ │ ├── __init__.py │ │ ├── agent_helpers.py │ │ ├── dspy_helpers.py │ │ ├── fixtures.py │ │ └── helpers.py ├── pyproject.toml ├── pytest.ini ├── requirements.txt └── sonar-project.properties ├── docs ├── docs │ ├── CNAME │ ├── assets │ │ ├── agent-1.jpeg │ │ ├── agent-2.jpeg │ │ ├── agent-3.jpeg │ │ ├── agent-4.jpeg │ │ ├── agent-5.jpeg │ │ ├── agent-evaluation-dspy.png │ │ ├── architecture-coordinator.svg │ │ ├── architecture-example-06-multi-agent-conversation.svg │ │ ├── architecture-gateway.svg │ │ ├── architecture-getting-started.svg │ │ ├── architecture-multi-agent-insurance-support-system.svg │ │ ├── avatar │ │ │ ├── audit-agent.png │ │ │ ├── billing-agent.png │ │ │ ├── claims-agent.png │ │ │ ├── escalation-agent.png │ │ │ ├── frontend-agent.png │ │ │ ├── policies-agent.png │ │ │ └── triage-agent.png │ │ ├── eggai-meta-framework-arch.png │ │ ├── eggai-word-and-figuremark.svg │ │ ├── example-00.png │ │ ├── example-01.png │ │ ├── example-02.png │ │ ├── example-03.png │ │ ├── example-04.png │ │ ├── example-05.png │ │ ├── example-06.png │ │ ├── example-07-chat.png │ │ ├── example-07.png │ │ ├── example-mcp.png │ │ ├── favicon.png │ │ ├── interoperability.png │ │ ├── logo.png │ │ ├── multi-agent-human-chat.png │ │ ├── react-agent-dspy.png │ │ ├── redpanda-console.png │ │ ├── safe-agents-guardrails.png │ │ ├── support-chat.png │ │ ├── system-architecture.svg │ │ ├── test_tsne.png │ │ ├── train_tsne.png │ │ ├── triage-agent.png │ │ ├── triage-custom-classifier-training.png │ │ └── triage-evaluation-report.png │ ├── concepts │ │ ├── agent.md │ │ ├── enterprise-ai-platform.md │ │ └── multi-agent-system.md │ ├── examples │ │ ├── agent_evaluation_dspy.md │ │ ├── agent_evaluation_dspy │ │ │ └── tests │ │ │ │ └── reports │ │ │ │ ├── classifier_v1.html │ │ │ │ ├── classifier_v2.html │ │ │ │ └── classifier_v3.html │ │ ├── coordinator.md │ │ ├── dspy_react.md │ │ ├── getting_started.md │ │ ├── langchain_tool_calling.md │ │ ├── litellm_agent.md │ │ ├── mcp.md │ │ ├── multi_agent_conversation.md │ │ ├── safe_agents_guardrails.md │ │ ├── shared_context.md │ │ ├── triage_agent.md │ │ └── websocket_gateway.md │ ├── index.md │ └── sdk │ │ ├── agent.md │ │ ├── channel.md │ │ ├── inmemory-transport.md │ │ ├── kafka-transport.md │ │ ├── message.md │ │ └── transport.md ├── mkdocs.yml ├── poetry.lock └── pyproject.toml ├── examples ├── a2a │ ├── README.md │ ├── __init__.py │ ├── client.py │ ├── requirements.txt │ └── simple_demo.py ├── agent_evaluation_dspy │ ├── .gitignore │ ├── README.md │ ├── __init__.py │ ├── datasets │ │ ├── __init__.py │ │ ├── loader.py │ │ ├── triage-testing.csv │ │ └── triage-training.csv │ ├── docker-compose.yml │ ├── requirements.txt │ ├── src │ │ ├── __init__.py │ │ ├── agents │ │ │ ├── __init__.py │ │ │ └── triage.py │ │ └── dspy_modules │ │ │ ├── __init__.py │ │ │ ├── classifier_v1.py │ │ │ ├── classifier_v2.py │ │ │ ├── classifier_v3.py │ │ │ ├── lm.py │ │ │ ├── optimizations_v3.json │ │ │ └── utils.py │ └── tests │ │ ├── __init__.py │ │ ├── reports │ │ ├── 20250110-165944-classifier_v1.html │ │ ├── 20250110-165948-classifier_v2.html │ │ ├── 20250110-165953-classifier_v3.html │ │ ├── classifier_v1.html │ │ ├── classifier_v2.html │ │ └── classifier_v3.html │ │ ├── test_classifier_v1.py │ │ ├── test_classifier_v2.py │ │ ├── test_classifier_v3.py │ │ ├── test_triage.py │ │ └── utilities.py ├── coordinator │ ├── README.md │ ├── coordinator.py │ ├── docker-compose.yml │ ├── email_agent.py │ ├── main.py │ ├── order_agent.py │ └── requirements.txt ├── dspy_react │ ├── .gitignore │ ├── README.md │ ├── docker-compose.yml │ ├── requirements.txt │ ├── src │ │ ├── __init__.py │ │ ├── agents │ │ │ ├── __init__.py │ │ │ └── react_agent.py │ │ ├── dspy_modules │ │ │ └── react_module.py │ │ └── main.py │ └── tests │ │ ├── __init__.py │ │ └── test_react_module.py ├── getting_started │ ├── README.md │ ├── email_agent.py │ ├── main.py │ ├── order_agent.py │ └── requirements.txt ├── langchain_tool_calling │ ├── README.md │ ├── docker-compose.yml │ ├── email_agent.py │ ├── main.py │ └── requirements.txt ├── litellm_agent │ ├── README.md │ ├── docker-compose.yml │ ├── escalate_agent.py │ ├── lite_llm_agent.py │ ├── main.py │ ├── requirements.txt │ └── support_agent.py ├── mcp │ ├── .env.example │ ├── Makefile │ ├── README.md │ ├── docker-compose.yml │ ├── docs │ │ └── mcp-example-architecture.png │ ├── eggai_adapter │ │ ├── __init__.py │ │ ├── client.py │ │ ├── dspy.py │ │ ├── mcp.py │ │ └── types.py │ ├── requirements.txt │ ├── schemas.py │ ├── start_console.py │ ├── start_ticketing_adapter.py │ ├── start_ticketing_agent.py │ └── start_ticketing_backend.py ├── multi_agent_conversation │ ├── README.md │ ├── chat_display.py │ ├── claims.py │ ├── docker-compose.yml │ ├── escalation.py │ ├── lite_llm_agent.py │ ├── main.py │ ├── memory.py │ ├── policy.py │ ├── requirements.txt │ ├── shared.py │ └── triage.py ├── safe_agents_guardrails │ ├── .gitignore │ ├── README.md │ ├── docker-compose.yml │ ├── requirements.txt │ ├── src │ │ ├── __init__.py │ │ ├── agents │ │ │ ├── __init__.py │ │ │ ├── answers_agent.py │ │ │ └── guardrail.py │ │ ├── dspy_modules │ │ │ ├── lm.py │ │ │ └── wiki_qa.py │ │ └── main.py │ └── tests │ │ ├── __init__.py │ │ └── test_answer_agent.py ├── shared_context │ ├── README.md │ ├── channels.py │ ├── docker-compose.yml │ ├── human_agent.py │ ├── main.py │ ├── memory_db.py │ ├── openai_client.py │ ├── products_agent.py │ ├── recommendation_agent.py │ └── requirements.txt ├── tool_calling │ ├── .env.example │ ├── Makefile │ ├── README.md │ ├── docker-compose.yml │ ├── requirements.txt │ ├── src │ │ ├── __init__.py │ │ ├── agents │ │ │ ├── __init__.py │ │ │ └── react_agent.py │ │ ├── config.py │ │ ├── dspy_modules │ │ │ └── react_module.py │ │ └── main.py │ └── tests │ │ ├── __init__.py │ │ └── test_react_module.py ├── triage_agent │ ├── .gitignore │ ├── README.md │ ├── __init__.py │ ├── docker-compose.yml │ ├── requirements.txt │ ├── src │ │ ├── __init__.py │ │ ├── agents │ │ │ ├── __init__.py │ │ │ └── triage.py │ │ ├── dspy_modules │ │ │ ├── __init__.py │ │ │ ├── lm.py │ │ │ ├── triage_module.py │ │ │ └── utils.py │ │ ├── loader.py │ │ └── triage-testing.csv │ └── tests │ │ ├── __init__.py │ │ ├── test_intent_classifier.py │ │ ├── test_triage.py │ │ └── utilities.py └── websocket_gateway │ ├── README.md │ ├── coordinator.py │ ├── docker-compose.yml │ ├── email_agent.py │ ├── gateway │ ├── server.py │ ├── websocket_agent.py │ └── websocket_manager.py │ ├── main.py │ ├── order_agent.py │ └── requirements.txt ├── scripts ├── __init__.py ├── run_all_tests.py └── run_tests.py └── sdk ├── cli ├── __init__.py ├── main.py ├── templates.py ├── templates │ ├── README.md.j2 │ ├── agent.py.j2 │ ├── agents_init.py.j2 │ ├── common_models.py.j2 │ ├── console.py.j2 │ ├── env.j2 │ ├── main.py.j2 │ └── requirements.txt.j2 └── wizard.py ├── eggai ├── __init__.py ├── adapters │ ├── __init__.py │ ├── a2a │ │ ├── __init__.py │ │ ├── config.py │ │ ├── executor.py │ │ └── plugin.py │ └── mcp │ │ ├── __init__.py │ │ ├── mcp.py │ │ └── models.py ├── agent.py ├── channel.py ├── hooks.py ├── schemas.py └── transport │ ├── __init__.py │ ├── base.py │ ├── defaults.py │ ├── inmemory.py │ └── kafka.py ├── poetry.lock ├── poetry.toml ├── pyproject.toml ├── requirements.txt └── tests ├── __init__.py ├── docker-compose.yml ├── test_catch_all.py ├── test_group_ids.py ├── test_inmemory_transport.py ├── test_kafka.py ├── test_namespace.py ├── test_simple_scenario.py └── test_typed_subscribe.py /.github/workflows/helm-release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Helm Chart 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "demo/helm/**" 9 | 10 | permissions: 11 | contents: write 12 | packages: write 13 | 14 | jobs: 15 | release: 16 | name: Helm Chart Release 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout source 21 | uses: actions/checkout@v3 22 | 23 | - name: Install Helm 24 | run: | 25 | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash 26 | 27 | - name: Log in to GitHub Container Registry 28 | run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin 29 | 30 | - name: Push chart to GHCR 31 | run: | 32 | version=$(yq '.version' demo/helm/Chart.yaml) 33 | helm registry login ghcr.io/eggai-tech/multi_agent_human_chat/helm --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} 34 | helm package demo/helm --version ${version} --destination packaged 35 | helm push packaged/eggai-multi-agent-chat-${version}.tgz oci://ghcr.io/${{ github.repository_owner }}/helm 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 EggAI Technologies GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /demo/.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = agents, libraries 3 | omit = 4 | */tests/* 5 | */test_*.py 6 | */*_test.py 7 | */*_test_*.py 8 | */shared_test_utils.py 9 | */conftest.py 10 | */__pycache__/* 11 | */venv/* 12 | */.venv/* 13 | 14 | [report] 15 | exclude_lines = 16 | pragma: no cover 17 | def __repr__ 18 | raise AssertionError 19 | raise NotImplementedError 20 | if __name__ == .__main__.: 21 | if TYPE_CHECKING: 22 | @abstract -------------------------------------------------------------------------------- /demo/.dockerignore: -------------------------------------------------------------------------------- 1 | # Python cache 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.pyc 6 | *.pyo 7 | *.pyd 8 | .Python 9 | pip-log.txt 10 | pip-delete-this-directory.txt 11 | 12 | # Virtual environments 13 | .venv/ 14 | venv/ 15 | ENV/ 16 | env/ 17 | 18 | # IDE 19 | .vscode/ 20 | .idea/ 21 | *.swp 22 | *.swo 23 | *~ 24 | 25 | # Testing and coverage 26 | .pytest_cache/ 27 | .coverage 28 | .coverage.* 29 | htmlcov/ 30 | .tox/ 31 | .nox/ 32 | coverage.xml 33 | *.cover 34 | *.log 35 | .hypothesis/ 36 | 37 | # Jupyter 38 | .ipynb_checkpoints/ 39 | *.ipynb 40 | 41 | # Documentation 42 | docs/ 43 | *.md 44 | README.* 45 | 46 | # Git 47 | .git/ 48 | .gitignore 49 | .gitattributes 50 | 51 | # Docker 52 | Dockerfile 53 | docker-compose*.yml 54 | .dockerignore 55 | 56 | # Build artifacts 57 | build/ 58 | dist/ 59 | *.egg-info/ 60 | .eggs/ 61 | 62 | # ML/Data artifacts 63 | *.pkl 64 | *.pth 65 | *.pt 66 | *.h5 67 | *.bin 68 | *.onnx 69 | *.safetensors 70 | checkpoints/ 71 | model_checkpoints/ 72 | mlflow_experiments/ 73 | .cache/ 74 | temp/ 75 | logs/ 76 | reports/ 77 | 78 | # Development files 79 | dev-requirements.txt 80 | Makefile 81 | pytest.ini 82 | pyproject.toml 83 | sonar-project.properties 84 | .ruff_cache/ 85 | 86 | # Helm charts 87 | helm/ 88 | 89 | # Test data and notebooks 90 | notebooks/ 91 | tests/ 92 | *test* 93 | conftest.py 94 | 95 | # Large data files 96 | data_sets/ 97 | artifacts/ 98 | 99 | # Temporary files 100 | *.tmp 101 | *.temp 102 | *.bak -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | agents/triage/dspy_modules/evaluation/reports/*.html 2 | reports/ 3 | tmp 4 | /agents/policies/vespa/artifacts/* 5 | 6 | # Model files and caches 7 | models/ 8 | dspy_cache/ 9 | -------------------------------------------------------------------------------- /demo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12-slim AS builder 2 | 3 | # Install build dependencies 4 | RUN apt-get update && apt-get install -y --no-install-recommends \ 5 | gcc \ 6 | g++ \ 7 | && rm -rf /var/lib/apt/lists/* 8 | 9 | # Set working directory 10 | WORKDIR /app 11 | 12 | # Copy and install requirements 13 | COPY requirements.txt . 14 | RUN pip install --upgrade pip && \ 15 | pip install --no-cache-dir --user -r requirements.txt 16 | 17 | # Final stage 18 | FROM python:3.12-slim 19 | 20 | # Install runtime dependencies only 21 | RUN apt-get update && apt-get install -y --no-install-recommends \ 22 | libgomp1 \ 23 | && rm -rf /var/lib/apt/lists/* 24 | 25 | WORKDIR /app 26 | 27 | # Copy installed packages from builder 28 | COPY --from=builder /root/.local /root/.local 29 | 30 | # Copy application code 31 | COPY agents /app/agents 32 | COPY libraries /app/libraries 33 | 34 | # Make sure scripts in .local are usable 35 | ENV PATH=/root/.local/bin:$PATH 36 | 37 | USER 1000 38 | 39 | ENTRYPOINT ["python", "-m"] 40 | -------------------------------------------------------------------------------- /demo/agents/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/__init__.py -------------------------------------------------------------------------------- /demo/agents/audit/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/audit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/audit/__init__.py -------------------------------------------------------------------------------- /demo/agents/audit/config.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from dotenv import load_dotenv 4 | from pydantic import Field 5 | from pydantic_settings import BaseSettings, SettingsConfigDict 6 | 7 | from .types import AuditCategory, AuditConfig 8 | 9 | load_dotenv() 10 | 11 | MESSAGE_CATEGORIES: Dict[str, AuditCategory] = { 12 | "agent_message": "User Communication", 13 | "billing_request": "Billing", 14 | "policy_request": "Policies", 15 | "escalation_request": "Escalation", 16 | "triage_request": "Triage", 17 | } 18 | 19 | class Settings(BaseSettings): 20 | app_name: str = Field(default="audit_agent") 21 | kafka_bootstrap_servers: str = Field(default="localhost:19092") 22 | kafka_ca_content: str = Field(default="") 23 | otel_endpoint: str = Field(default="http://localhost:4318") 24 | prometheus_metrics_port: int = Field(default=9096) 25 | 26 | debug_logging_enabled: bool = Field(default=False) 27 | audit_channel_name: str = Field(default="audit_logs") 28 | default_category: AuditCategory = Field(default="Other") 29 | 30 | model_config = SettingsConfigDict( 31 | env_prefix="AUDIT_", env_file=".env", env_ignore_empty=True, extra="ignore" 32 | ) 33 | 34 | settings = Settings() 35 | 36 | audit_config = AuditConfig( 37 | message_categories=MESSAGE_CATEGORIES, 38 | default_category=settings.default_category, 39 | enable_debug_logging=settings.debug_logging_enabled, 40 | audit_channel_name=settings.audit_channel_name, 41 | ) 42 | -------------------------------------------------------------------------------- /demo/agents/audit/main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | 4 | from eggai import eggai_main 5 | from eggai.transport import eggai_set_default_transport 6 | 7 | from libraries.communication.transport import create_kafka_transport 8 | from libraries.observability.logger import get_console_logger 9 | from libraries.observability.tracing import init_telemetry 10 | 11 | from .config import settings 12 | 13 | eggai_set_default_transport( 14 | lambda: create_kafka_transport( 15 | bootstrap_servers=settings.kafka_bootstrap_servers, 16 | ssl_cert=settings.kafka_ca_content, 17 | ) 18 | ) 19 | 20 | from .agent import audit_agent 21 | 22 | logger = get_console_logger("audit_agent") 23 | logger.setLevel(logging.INFO) 24 | 25 | 26 | @eggai_main 27 | async def main(): 28 | logger.info(f"Starting {settings.app_name}") 29 | 30 | init_telemetry(app_name=settings.app_name, endpoint=settings.otel_endpoint) 31 | logger.info(f"Telemetry initialized for {settings.app_name}") 32 | 33 | logger.info( 34 | f"Using Kafka transport with servers: {settings.kafka_bootstrap_servers}" 35 | ) 36 | 37 | await audit_agent.start() 38 | logger.info(f"{settings.app_name} started successfully") 39 | 40 | try: 41 | await asyncio.Future() 42 | except asyncio.CancelledError: 43 | logger.info("Audit agent task cancelled") 44 | 45 | 46 | if __name__ == "__main__": 47 | try: 48 | asyncio.run(main()) 49 | except KeyboardInterrupt: 50 | logger.info("Shutting down audit agent") 51 | except Exception as e: 52 | logger.error(f"Error in main: {e}", exc_info=True) 53 | -------------------------------------------------------------------------------- /demo/agents/audit/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/audit/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/audit/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import pytest 4 | 5 | 6 | @pytest.fixture(scope="session") 7 | def event_loop(): 8 | """Create a fresh event loop for the test session.""" 9 | loop = asyncio.new_event_loop() 10 | asyncio.set_event_loop(loop) 11 | yield loop 12 | loop.close() 13 | -------------------------------------------------------------------------------- /demo/agents/audit/types.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Any, Dict, Literal, Optional 3 | 4 | from pydantic import BaseModel, Field 5 | 6 | AuditCategory = Literal[ 7 | "User Communication", 8 | "Billing", 9 | "Policies", 10 | "Escalation", 11 | "Triage", 12 | "Other", 13 | "Error", 14 | ] 15 | 16 | class AuditConfig(BaseModel): 17 | message_categories: Dict[str, AuditCategory] = Field(default_factory=dict) 18 | default_category: AuditCategory = Field(default="Other") 19 | enable_debug_logging: bool = Field(default=False) 20 | audit_channel_name: str = Field(default="audit_logs") 21 | 22 | model_config = {"validate_assignment": True, "extra": "forbid"} 23 | 24 | class AuditEvent(BaseModel): 25 | message_id: str = Field(...) 26 | message_type: str = Field(...) 27 | message_source: str = Field(...) 28 | channel: str = Field(...) 29 | category: AuditCategory = Field(...) 30 | audit_timestamp: datetime = Field(default_factory=datetime.now) 31 | content: Optional[str] = Field(default=None) 32 | error: Optional[Dict[str, str]] = Field(default=None) 33 | 34 | def to_dict(self) -> Dict[str, Any]: 35 | result = self.model_dump() 36 | result["audit_timestamp"] = self.audit_timestamp.isoformat() 37 | return result 38 | 39 | model_config = {"validate_assignment": True} -------------------------------------------------------------------------------- /demo/agents/billing/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/billing/README.md: -------------------------------------------------------------------------------- 1 | # Billing Agent 2 | 3 | Handles payment and financial inquiries for insurance policies. 4 | 5 | ## What it does 6 | - Retrieves billing info (premium amounts, due dates, payment status) 7 | - Updates payment information 8 | - Requires policy number for privacy 9 | 10 | ## Quick Start 11 | ```bash 12 | make start-billing 13 | ``` 14 | 15 | ## Configuration 16 | ```bash 17 | BILLING_LANGUAGE_MODEL=lm_studio/gemma-3-12b-it # Or openai/gpt-4o-mini 18 | ``` 19 | 20 | ## Tools 21 | - `get_billing_info(policy_number)` - Returns premium, due date, status 22 | - `update_billing_info(policy_number, field, value)` - Updates payment info 23 | 24 | ## Testing 25 | ```bash 26 | make test-billing-agent 27 | ``` -------------------------------------------------------------------------------- /demo/agents/billing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/billing/__init__.py -------------------------------------------------------------------------------- /demo/agents/billing/config.py: -------------------------------------------------------------------------------- 1 | from dotenv import load_dotenv 2 | from pydantic import Field 3 | from pydantic_settings import SettingsConfigDict 4 | 5 | from libraries.core import BaseAgentConfig 6 | 7 | from .types import ModelConfig 8 | 9 | load_dotenv() 10 | 11 | MESSAGE_TYPE_BILLING_REQUEST = "billing_request" 12 | 13 | class Settings(BaseAgentConfig): 14 | app_name: str = Field(default="billing_agent") 15 | prometheus_metrics_port: int = Field( 16 | default=9095, description="Port for Prometheus metrics server" 17 | ) 18 | 19 | billing_database_path: str = Field(default="") 20 | 21 | model_name: str = Field(default="billing_react", description="Name of the model") 22 | max_iterations: int = Field(default=5, ge=1, le=10) 23 | use_tracing: bool = Field(default=True) 24 | cache_enabled: bool = Field(default=False) 25 | timeout_seconds: float = Field(default=30.0, ge=1.0) 26 | truncation_length: int = Field(default=15000, ge=1000) 27 | 28 | model_config = SettingsConfigDict( 29 | env_prefix="BILLING_", env_file=".env", env_ignore_empty=True, extra="ignore" 30 | ) 31 | 32 | settings = Settings() 33 | 34 | model_config = ModelConfig( 35 | name=settings.model_name, 36 | max_iterations=settings.max_iterations, 37 | use_tracing=settings.use_tracing, 38 | cache_enabled=settings.cache_enabled, 39 | timeout_seconds=settings.timeout_seconds, 40 | truncation_length=settings.truncation_length, 41 | ) 42 | -------------------------------------------------------------------------------- /demo/agents/billing/dspy_modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/billing/dspy_modules/__init__.py -------------------------------------------------------------------------------- /demo/agents/billing/dspy_modules/evaluation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/billing/dspy_modules/evaluation/__init__.py -------------------------------------------------------------------------------- /demo/agents/billing/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/billing/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/billing/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import pytest 4 | 5 | 6 | @pytest.fixture(scope="session") 7 | def event_loop(): 8 | """Ensure a fresh event loop for the test session to avoid 'RuntimeError: Event loop is closed'.""" 9 | loop = asyncio.new_event_loop() 10 | asyncio.set_event_loop(loop) 11 | yield loop 12 | loop.close() 13 | -------------------------------------------------------------------------------- /demo/agents/billing/tests/test_module.py: -------------------------------------------------------------------------------- 1 | from agents.billing.config import settings 2 | from libraries.ml.dspy.language_model import dspy_set_language_model 3 | from libraries.observability.logger import get_console_logger 4 | 5 | logger = get_console_logger("billing_agent.tests.module") 6 | 7 | # Configure language model based on settings with caching disabled for accuracy 8 | dspy_lm = dspy_set_language_model(settings, overwrite_cache_enabled=False) -------------------------------------------------------------------------------- /demo/agents/billing/types.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | from libraries.communication.protocol import ChatMessage as ChatMessage 6 | from libraries.core import ModelConfig as BaseModelConfig 7 | from libraries.core import ModelResult as ModelResult 8 | 9 | 10 | class ModelConfig(BaseModelConfig): 11 | name: str = Field(default="billing_react", description="Name of the model") 12 | 13 | class BillingRecord(BaseModel): 14 | 15 | policy_number: str = Field(..., description="Unique identifier for the policy") 16 | customer_name: str = Field(..., description="Name of the customer") 17 | amount_due: float = Field(..., description="Amount due", ge=0) 18 | due_date: str = Field(..., description="Due date for payment (YYYY-MM-DD)") 19 | billing_status: str = Field(..., description="Current billing status") 20 | billing_cycle: str = Field( 21 | ..., description="Billing cycle (monthly, quarterly, etc.)" 22 | ) 23 | last_payment_date: Optional[str] = Field( 24 | None, description="Date of last payment (YYYY-MM-DD)" 25 | ) 26 | last_payment_amount: Optional[float] = Field( 27 | None, description="Amount of last payment", ge=0 28 | ) 29 | next_payment_amount: Optional[float] = Field( 30 | None, description="Amount of next payment", ge=0 31 | ) 32 | contact_email: Optional[str] = Field(None, description="Contact email address") 33 | contact_phone: Optional[str] = Field(None, description="Contact phone number") 34 | 35 | model_config = {"extra": "forbid"} 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /demo/agents/claims/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/claims/README.md: -------------------------------------------------------------------------------- 1 | # Claims Agent 2 | 3 | Manages insurance claim inquiries, status checks, and new claim filing. 4 | 5 | ## What it does 6 | - Files new insurance claims 7 | - Checks claim status by claim number 8 | - Provides claim history for policies 9 | 10 | ## Quick Start 11 | ```bash 12 | make start-claims 13 | ``` 14 | 15 | ## Configuration 16 | ```bash 17 | CLAIMS_LANGUAGE_MODEL=lm_studio/gemma-3-12b-it # Or openai/gpt-4o-mini 18 | ``` 19 | 20 | ## Tools 21 | - `get_claim_status(claim_number)` - Returns status and next steps 22 | - `file_new_claim(policy_number, incident_details)` - Creates new claim 23 | - `get_claim_history(policy_number)` - Lists all claims for a policy 24 | 25 | ## Testing 26 | ```bash 27 | make test-claims-agent 28 | ``` -------------------------------------------------------------------------------- /demo/agents/claims/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/claims/__init__.py -------------------------------------------------------------------------------- /demo/agents/claims/config.py: -------------------------------------------------------------------------------- 1 | from dotenv import load_dotenv 2 | from pydantic import Field 3 | from pydantic_settings import SettingsConfigDict 4 | 5 | from libraries.core import BaseAgentConfig 6 | 7 | from .types import ModelConfig 8 | 9 | load_dotenv() 10 | 11 | MESSAGE_TYPE_CLAIM_REQUEST = "claim_request" 12 | 13 | 14 | class Settings(BaseAgentConfig): 15 | app_name: str = Field(default="claims_agent") 16 | prometheus_metrics_port: int = Field(default=9092) 17 | 18 | model_name: str = Field(default="claims_react", description="Name of the model") 19 | max_iterations: int = Field(default=5, ge=1, le=10) 20 | use_tracing: bool = Field(default=True) 21 | cache_enabled: bool = Field(default=False) 22 | timeout_seconds: float = Field(default=30.0, ge=1.0) 23 | truncation_length: int = Field(default=15000, ge=1000) 24 | 25 | model_config = SettingsConfigDict( 26 | env_prefix="CLAIMS_", env_file=".env", env_ignore_empty=True, extra="ignore" 27 | ) 28 | 29 | 30 | settings = Settings() 31 | 32 | model_config = ModelConfig( 33 | name=settings.model_name, 34 | max_iterations=settings.max_iterations, 35 | use_tracing=settings.use_tracing, 36 | cache_enabled=settings.cache_enabled, 37 | timeout_seconds=settings.timeout_seconds, 38 | truncation_length=settings.truncation_length, 39 | ) 40 | -------------------------------------------------------------------------------- /demo/agents/claims/dspy_modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/claims/dspy_modules/__init__.py -------------------------------------------------------------------------------- /demo/agents/claims/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/claims/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/claims/tests/conftest.py: -------------------------------------------------------------------------------- 1 | """Test configuration for claims agent tests.""" 2 | 3 | import asyncio 4 | from unittest.mock import AsyncMock, MagicMock 5 | 6 | import pytest 7 | 8 | 9 | @pytest.fixture(scope="function") 10 | def event_loop(): 11 | """Create an instance of the default event loop for the test session.""" 12 | loop = asyncio.new_event_loop() 13 | yield loop 14 | loop.close() 15 | 16 | 17 | @pytest.fixture 18 | def mock_language_model(monkeypatch): 19 | """Mock the language model to avoid initialization issues in tests.""" 20 | # Mock the language model initialization 21 | mock_lm = MagicMock() 22 | monkeypatch.setattr("dspy.LM", lambda *args, **kwargs: mock_lm) 23 | monkeypatch.setattr( 24 | "libraries.dspy_set_language_model.dspy_set_language_model", 25 | lambda *args, **kwargs: mock_lm, 26 | ) 27 | return mock_lm 28 | 29 | 30 | @pytest.fixture 31 | def mock_claims_response(): 32 | """Simple mock for claims responses.""" 33 | 34 | async def mock_response(*args, **kwargs): 35 | from dspy import Prediction 36 | 37 | yield Prediction(final_response="I'll help you with your claims request.") 38 | 39 | return mock_response 40 | 41 | 42 | @pytest.fixture 43 | def mock_stream_channel(monkeypatch): 44 | """Mock the human stream channel for testing.""" 45 | mock_publish = AsyncMock() 46 | monkeypatch.setattr( 47 | "agents.claims.agent.human_stream_channel.publish", mock_publish 48 | ) 49 | return mock_publish 50 | 51 | 52 | @pytest.fixture 53 | def mock_human_channel(monkeypatch): 54 | """Mock the human channel for testing.""" 55 | mock_publish = AsyncMock() 56 | monkeypatch.setattr("agents.claims.agent.human_channel.publish", mock_publish) 57 | return mock_publish 58 | -------------------------------------------------------------------------------- /demo/agents/escalation/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/escalation/README.md: -------------------------------------------------------------------------------- 1 | # Escalation Agent 2 | 3 | Handles complex issues, complaints, and requests requiring special attention. 4 | 5 | ## What it does 6 | - Creates support tickets for complex issues 7 | - Routes to appropriate departments 8 | - Tracks ticket status and updates 9 | - Handles complaints professionally 10 | 11 | ## Quick Start 12 | ```bash 13 | make start-escalation 14 | ``` 15 | 16 | ## Configuration 17 | ```bash 18 | ESCALATION_LANGUAGE_MODEL=lm_studio/gemma-3-12b-it # Or openai/gpt-4o-mini 19 | ``` 20 | 21 | ## Tools 22 | - `create_ticket(description, department, priority)` - Creates support ticket 23 | - `get_ticket_status(ticket_id)` - Returns current status 24 | - `update_ticket(ticket_id, update)` - Adds notes to ticket 25 | 26 | Departments: Technical Support, Billing, Sales 27 | 28 | ## Testing 29 | ```bash 30 | make test-escalation-agent 31 | ``` -------------------------------------------------------------------------------- /demo/agents/escalation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/escalation/__init__.py -------------------------------------------------------------------------------- /demo/agents/escalation/dspy_modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/escalation/dspy_modules/__init__.py -------------------------------------------------------------------------------- /demo/agents/escalation/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/escalation/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/escalation/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from unittest.mock import AsyncMock, MagicMock 3 | 4 | import pytest 5 | 6 | 7 | @pytest.fixture(scope="session") 8 | def event_loop(): 9 | """Ensure a fresh event loop for the test session to avoid 'RuntimeError: Event loop is closed'.""" 10 | loop = asyncio.new_event_loop() 11 | asyncio.set_event_loop(loop) 12 | yield loop 13 | loop.close() 14 | 15 | 16 | @pytest.fixture 17 | def mock_language_model(monkeypatch): 18 | """Mock the language model to avoid initialization issues in tests.""" 19 | # Mock the language model initialization 20 | mock_lm = MagicMock() 21 | monkeypatch.setattr("dspy.LM", lambda *args, **kwargs: mock_lm) 22 | monkeypatch.setattr( 23 | "libraries.dspy_set_language_model.dspy_set_language_model", 24 | lambda *args, **kwargs: mock_lm, 25 | ) 26 | return mock_lm 27 | 28 | 29 | @pytest.fixture 30 | def mock_escalation_response(): 31 | """Simple mock for escalation responses.""" 32 | 33 | async def mock_response(*args, **kwargs): 34 | from dspy import Prediction 35 | 36 | yield Prediction(final_response="I'll help you with your escalation request.") 37 | 38 | return mock_response 39 | 40 | 41 | @pytest.fixture 42 | def mock_stream_channel(monkeypatch): 43 | """Mock the human stream channel for testing.""" 44 | mock_publish = AsyncMock() 45 | monkeypatch.setattr( 46 | "agents.escalation.agent.human_stream_channel.publish", mock_publish 47 | ) 48 | return mock_publish 49 | -------------------------------------------------------------------------------- /demo/agents/escalation/types.py: -------------------------------------------------------------------------------- 1 | from typing import Literal, Optional, TypedDict 2 | 3 | from pydantic import BaseModel, Field 4 | 5 | from libraries.communication.protocol import ( 6 | ChatMessage as ChatMessage, 7 | ) 8 | from libraries.communication.protocol import ( 9 | MessageData as MessageData, 10 | ) 11 | from libraries.core import ( 12 | ModelConfig as BaseModelConfig, 13 | ) 14 | from libraries.core import ( 15 | ModelResult as ModelResult, 16 | ) 17 | 18 | TicketDepartment = Literal["Technical Support", "Billing", "Sales"] 19 | 20 | WorkflowStep = Literal["ask_additional_data", "ask_confirmation", "create_ticket"] 21 | 22 | ConfirmationResponse = Literal["yes", "no"] 23 | 24 | 25 | 26 | class TicketingRequestMessage(TypedDict): 27 | 28 | id: str 29 | type: Literal["ticketing_request"] 30 | source: str 31 | data: MessageData 32 | traceparent: Optional[str] 33 | tracestate: Optional[str] 34 | 35 | 36 | class ModelConfig(BaseModelConfig): 37 | 38 | name: str = Field("ticketing_agent", description="Name of the DSPy ticketing model") 39 | 40 | 41 | 42 | class TicketInfo(BaseModel): 43 | 44 | id: str = Field(..., description="Unique identifier for the ticket") 45 | policy_number: str = Field(description="Policy number associated with the ticket") 46 | department: TicketDepartment = Field(..., description="Department for the ticket") 47 | title: str = Field(..., description="Title of the ticket") 48 | contact_info: str = Field(..., description="Contact information of the user") 49 | created_at: str = Field(..., description="Creation timestamp") 50 | 51 | model_config = {"extra": "forbid"} 52 | 53 | 54 | DspyModelConfig = ModelConfig 55 | -------------------------------------------------------------------------------- /demo/agents/frontend/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/frontend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/frontend/__init__.py -------------------------------------------------------------------------------- /demo/agents/frontend/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from pydantic import Field 4 | from pydantic_settings import SettingsConfigDict 5 | 6 | from libraries.core import BaseAgentConfig 7 | 8 | 9 | class Settings(BaseAgentConfig): 10 | app_name: str = Field(default="frontend_agent") 11 | prometheus_metrics_port: int = Field(default=9097, description="Port for Prometheus metrics server") 12 | 13 | host: str = Field(default="127.0.0.1") 14 | port: int = Field(default=8000) 15 | log_level: str = Field(default="info") 16 | 17 | websocket_path: str = Field(default="/ws") 18 | websocket_ping_interval: float = Field(default=30.0) 19 | websocket_ping_timeout: float = Field(default=10.0) 20 | 21 | public_dir: str = Field(default="") 22 | 23 | @property 24 | def default_public_dir(self) -> str: 25 | if not self.public_dir: 26 | return os.path.join(os.path.dirname(os.path.abspath(__file__)), "public") 27 | return self.public_dir 28 | 29 | model_config = SettingsConfigDict( 30 | env_prefix="FRONTEND_", env_file=".env", env_ignore_empty=True, extra="ignore" 31 | ) 32 | 33 | 34 | settings = Settings() 35 | -------------------------------------------------------------------------------- /demo/agents/frontend/guardrails.py: -------------------------------------------------------------------------------- 1 | from guardrails import AsyncGuard 2 | 3 | from libraries.observability.logger import get_console_logger 4 | 5 | logger = get_console_logger("frontend_agent") 6 | 7 | try: 8 | from guardrails.hub import ToxicLanguage 9 | except ImportError: 10 | logger.warning("ToxicLanguage validator not found in guardrails.hub; disabling guardrails") 11 | ToxicLanguage = None 12 | 13 | _toxic_language_guard = None 14 | if ToxicLanguage: 15 | _toxic_language_guard = AsyncGuard().use( 16 | ToxicLanguage, 17 | threshold=0.5, 18 | validation_method="sentence", 19 | on_fail="noop", 20 | ) 21 | 22 | 23 | async def toxic_language_guard(text: str) -> str | None: 24 | """ 25 | Validate and filter text via ToxicLanguage guardrail. 26 | 27 | Returns the sanitized text if passed, otherwise None. 28 | If ToxicLanguage is unavailable, returns text unchanged. 29 | """ 30 | if _toxic_language_guard is None: 31 | return text 32 | result = await _toxic_language_guard.validate(text) 33 | if result.validation_passed is False: 34 | return None 35 | return result.validated_output 36 | -------------------------------------------------------------------------------- /demo/agents/frontend/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/frontend/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/frontend/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import pytest 4 | 5 | 6 | @pytest.fixture(scope="session") 7 | def event_loop(): 8 | """Ensure a fresh event loop for the test session to avoid 'RuntimeError: Event loop is closed'.""" 9 | loop = asyncio.new_event_loop() 10 | asyncio.set_event_loop(loop) 11 | yield loop 12 | loop.close() 13 | -------------------------------------------------------------------------------- /demo/agents/frontend/tests/test_main_endpoint.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from fastapi.testclient import TestClient 3 | 4 | from ..main import api, settings 5 | 6 | 7 | @pytest.fixture(autouse=True) 8 | def temp_public_dir(tmp_path, monkeypatch): 9 | """Monkey-patch settings.public_dir to a temporary directory.""" 10 | monkeypatch.setattr(settings, "public_dir", str(tmp_path)) 11 | return tmp_path 12 | 13 | 14 | def test_read_root_success(temp_public_dir): 15 | """When index.html exists, GET / returns its contents.""" 16 | html_file = temp_public_dir / "index.html" 17 | content = "
OK" 18 | html_file.write_text(content, encoding="utf-8") 19 | client = TestClient(api) 20 | response = client.get("/") 21 | assert response.status_code == 200 22 | assert response.text == content 23 | 24 | 25 | def test_read_root_not_found(temp_public_dir): 26 | """When index.html is missing, GET / returns 404.""" 27 | client = TestClient(api) 28 | response = client.get("/") 29 | assert response.status_code == 404 30 | 31 | 32 | def test_read_root_error(temp_public_dir, monkeypatch): 33 | """When reading index.html raises an error, GET / returns 500.""" 34 | html_file = temp_public_dir / "index.html" 35 | html_file.write_text("data", encoding="utf-8") 36 | # Simulate aiofiles.open() throwing an unexpected error 37 | import aiofiles 38 | monkeypatch.setattr( 39 | aiofiles, 40 | 'open', 41 | lambda *args, **kwargs: (_ for _ in ()).throw(Exception("fail")), 42 | ) 43 | client = TestClient(api) 44 | response = client.get("/") 45 | assert response.status_code == 500 46 | assert "An error occurred" in response.json().get("detail", "") -------------------------------------------------------------------------------- /demo/agents/frontend/types.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import Literal, Optional, TypedDict 3 | 4 | from libraries.communication.protocol import ( 5 | MessageData, 6 | ) 7 | from libraries.core import ( 8 | ModelConfig as BaseModelConfig, 9 | ) 10 | 11 | WebSocketStateType = Literal["connected", "disconnected", "connecting"] 12 | 13 | 14 | class UserMessage(TypedDict): 15 | 16 | id: str 17 | type: Literal["user_message"] 18 | source: Literal["Frontend"] 19 | data: MessageData 20 | traceparent: Optional[str] 21 | tracestate: Optional[str] 22 | 23 | 24 | class AgentResponseMessage(TypedDict): 25 | 26 | id: str 27 | type: Literal["agent_message"] 28 | source: str 29 | data: MessageData 30 | traceparent: Optional[str] 31 | tracestate: Optional[str] 32 | 33 | 34 | class ModelConfig(BaseModelConfig): 35 | pass 36 | 37 | 38 | class MessageType(str, Enum): 39 | USER_MESSAGE = "user_message" 40 | AGENT_MESSAGE = "agent_message" 41 | AGENT_MESSAGE_STREAM_START = "agent_message_stream_start" 42 | AGENT_MESSAGE_STREAM_WAITING_MESSAGE = "agent_message_stream_waiting_message" 43 | AGENT_MESSAGE_STREAM_CHUNK = "agent_message_stream_chunk" 44 | AGENT_MESSAGE_STREAM_END = "agent_message_stream_end" 45 | ASSISTANT_MESSAGE = "assistant_message" 46 | ASSISTANT_MESSAGE_STREAM_START = "assistant_message_stream_start" 47 | ASSISTANT_MESSAGE_STREAM_WAITING_MESSAGE = "assistant_message_stream_waiting_message" 48 | ASSISTANT_MESSAGE_STREAM_CHUNK = "assistant_message_stream_chunk" 49 | ASSISTANT_MESSAGE_STREAM_END = "assistant_message_stream_end" -------------------------------------------------------------------------------- /demo/agents/policies/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/policies/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/api/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/api/dependencies.py: -------------------------------------------------------------------------------- 1 | from functools import lru_cache 2 | from typing import Annotated 3 | 4 | from fastapi import Depends 5 | from sentence_transformers import SentenceTransformer 6 | 7 | from agents.policies.agent.services.document_service import DocumentService 8 | from agents.policies.agent.services.reindex_service import ReindexService 9 | from agents.policies.agent.services.search_service import SearchService 10 | from libraries.integrations.vespa import VespaClient 11 | from libraries.observability.logger import get_console_logger 12 | 13 | logger = get_console_logger("policies_api_dependencies") 14 | 15 | 16 | @lru_cache() 17 | def get_vespa_client() -> VespaClient: 18 | logger.info("Creating Vespa client instance") 19 | return VespaClient() 20 | 21 | 22 | @lru_cache() 23 | def get_embedding_model() -> SentenceTransformer: 24 | logger.info("Loading embedding model") 25 | return SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2") 26 | 27 | 28 | def get_document_service( 29 | vespa_client: Annotated[VespaClient, Depends(get_vespa_client)] 30 | ) -> DocumentService: 31 | return DocumentService(vespa_client) 32 | 33 | 34 | def get_search_service( 35 | vespa_client: Annotated[VespaClient, Depends(get_vespa_client)], 36 | embedding_model: Annotated[SentenceTransformer, Depends(get_embedding_model)] 37 | ) -> SearchService: 38 | return SearchService(vespa_client, embedding_model) 39 | 40 | 41 | def get_reindex_service( 42 | vespa_client: Annotated[VespaClient, Depends(get_vespa_client)] 43 | ) -> ReindexService: 44 | return ReindexService(vespa_client) -------------------------------------------------------------------------------- /demo/agents/policies/agent/api/middleware.py: -------------------------------------------------------------------------------- 1 | import time 2 | from typing import Callable 3 | 4 | from fastapi import Request, Response 5 | from fastapi.responses import JSONResponse 6 | 7 | from libraries.observability.logger import get_console_logger 8 | 9 | logger = get_console_logger("policies_api_middleware") 10 | 11 | 12 | async def add_process_time_header(request: Request, call_next: Callable) -> Response: 13 | start_time = time.time() 14 | response = await call_next(request) 15 | process_time = time.time() - start_time 16 | response.headers["X-Process-Time"] = str(process_time) 17 | return response 18 | 19 | 20 | async def catch_exceptions_middleware(request: Request, call_next: Callable) -> Response: 21 | try: 22 | return await call_next(request) 23 | except Exception as e: 24 | # Log the error with full traceback 25 | logger.error(f"Unhandled exception: {e}", exc_info=True) 26 | 27 | # Return generic error response to avoid exposing internals 28 | return JSONResponse( 29 | status_code=500, 30 | content={"detail": "An unexpected error occurred. Please try again later."} 31 | ) 32 | 33 | 34 | async def add_security_headers(request: Request, call_next: Callable) -> Response: 35 | response = await call_next(request) 36 | 37 | # Add security headers 38 | response.headers["X-Content-Type-Options"] = "nosniff" 39 | response.headers["X-Frame-Options"] = "DENY" 40 | response.headers["X-XSS-Protection"] = "1; mode=block" 41 | response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains" 42 | 43 | return response -------------------------------------------------------------------------------- /demo/agents/policies/agent/optimization/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/optimization/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/optimization/optimized_policies_simba.json: -------------------------------------------------------------------------------- 1 | { 2 | "module_name": "PolicyAgentSignature", 3 | "metadata": { 4 | "optimization_method": "SIMBA", 5 | "tools": ["get_personal_policy_details", "search_policy_documentation"], 6 | "description": "Optimized policy agent with personal policy lookup and documentation search" 7 | }, 8 | "prompts": { 9 | "instructions": "You are a Policy Agent for an insurance company.\n\nROLE:\n- Help with both personal policy information and general policy questions\n- Your primary responsibility is data privacy - never reveal personal policy details without a valid policy number\n- Always call tools to get real data, never use hardcoded examples\n\nTOOLS AVAILABLE:\n1. get_personal_policy_details - Get specific policy data from database using policy number\n2. search_policy_documentation - Search policy documentation and coverage information\n\nDECISION LOGIC:\n- Personal policy queries (my premium, my policy details): Use get_personal_policy_details with policy number\n- General coverage questions (what's covered, how does it work): Use search_policy_documentation\n- If personal info requested without policy number: Ask for policy number\n\nWORKFLOW:\n1. Determine if user wants personal data or general information\n2. For personal queries: Check for policy number, call get_personal_policy_details\n3. For general queries: Call search_policy_documentation with relevant query\n4. Always use actual tool responses\n\nGUIDELINES:\n- Be professional and helpful\n- Include policy numbers when providing personal information\n- Format dates as YYYY-MM-DD, amounts with $ sign\n- Never skip tool calls when data is needed" 10 | } 11 | } -------------------------------------------------------------------------------- /demo/agents/policies/agent/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/services/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/tools/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/tools/database/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/tools/database/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/tools/database/example_data.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, List 2 | 3 | # Sample policies for testing and demonstration 4 | EXAMPLE_POLICIES: List[Dict] = [ 5 | { 6 | "policy_number": "A12345", 7 | "name": "John Doe", 8 | "policy_category": "home", 9 | "premium_amount": 500, 10 | "due_date": "2026-03-01", 11 | "status": "active", 12 | }, 13 | { 14 | "policy_number": "B67890", 15 | "name": "Jane Smith", 16 | "policy_category": "life", 17 | "premium_amount": 300, 18 | "due_date": "2026-03-15", 19 | "status": "active", 20 | }, 21 | { 22 | "policy_number": "C24680", 23 | "name": "Alice Johnson", 24 | "policy_category": "auto", 25 | "premium_amount": 400, 26 | "due_date": "2026-03-01", 27 | "status": "active", 28 | }, 29 | ] 30 | 31 | # This would typically come from environment configuration 32 | USE_EXAMPLE_DATA = True # Set to False in production -------------------------------------------------------------------------------- /demo/agents/policies/agent/tools/retrieval/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/agent/tools/retrieval/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/agent/types.py: -------------------------------------------------------------------------------- 1 | from typing import Literal 2 | 3 | from pydantic import Field 4 | 5 | from libraries.communication.protocol import ( 6 | ChatMessage as ChatMessage, 7 | ) 8 | from libraries.core import ( 9 | ModelConfig as BaseModelConfig, 10 | ) 11 | 12 | PolicyCategory = Literal["auto", "life", "home", "health"] 13 | 14 | 15 | class ModelConfig(BaseModelConfig): 16 | name: str = Field("policies_react", description="Name of the model") 17 | date_format: str = Field("YYYY-MM-DD", description="Required date format for responses") 18 | -------------------------------------------------------------------------------- /demo/agents/policies/agent/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .async_helpers import run_async_safe as run_async_safe 2 | -------------------------------------------------------------------------------- /demo/agents/policies/ingestion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/ingestion/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/ingestion/workflows/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/ingestion/workflows/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/ingestion/workflows/activities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/ingestion/workflows/activities/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import pytest 4 | 5 | 6 | @pytest.fixture(scope="function") 7 | def event_loop(): 8 | """Ensure a fresh event loop for each test to avoid 'RuntimeError: Event loop is closed'.""" 9 | loop = asyncio.new_event_loop() 10 | asyncio.set_event_loop(loop) 11 | yield loop 12 | loop.close() 13 | -------------------------------------------------------------------------------- /demo/agents/policies/tests/retrieval_performance/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/tests/retrieval_performance/__init__.py -------------------------------------------------------------------------------- /demo/agents/policies/tests/retrieval_performance/data_utilities.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | from typing import List 4 | 5 | from .models import RetrievalTestCase 6 | 7 | 8 | def load_qa_pairs_from_json() -> List[RetrievalTestCase]: 9 | """Load test cases from filtered QA pairs JSON file.""" 10 | json_path = Path(__file__).parent / "filtered_qa_pairs.json" 11 | 12 | with open(json_path, "r") as f: 13 | qa_pairs = json.load(f) 14 | 15 | test_cases = [] 16 | for qa_pair in qa_pairs: 17 | test_cases.append( 18 | RetrievalTestCase( 19 | id=qa_pair["qa_pair_id"], 20 | question=qa_pair["question"], 21 | expected_answer=qa_pair["answer"], 22 | expected_context=qa_pair["context"], 23 | category=qa_pair.get("source_document", "").replace(".md", ""), 24 | description=f"Test case from {qa_pair.get('source_document', 'unknown')}", 25 | ) 26 | ) 27 | 28 | return test_cases 29 | 30 | 31 | def get_retrieval_test_cases() -> List[RetrievalTestCase]: 32 | """Get test dataset - now loads from JSON file with context-based evaluation.""" 33 | return load_qa_pairs_from_json() 34 | -------------------------------------------------------------------------------- /demo/agents/policies/vespa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/policies/vespa/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/Makefile: -------------------------------------------------------------------------------- 1 | ../../Makefile -------------------------------------------------------------------------------- /demo/agents/triage/README.md: -------------------------------------------------------------------------------- 1 | # Triage Agent 2 | 3 | ML-powered message classification and routing to specialized agents. 4 | 5 | ## What it does 6 | - Classifies incoming messages using ML 7 | - Routes to: Billing, Claims, Policies, or Escalation agents 8 | - Handles small talk directly 9 | - Supports multiple classifier versions (v0-v5) 10 | 11 | ## Quick Start 12 | ```bash 13 | make start-triage 14 | ``` 15 | 16 | ## Configuration 17 | ```bash 18 | TRIAGE_LANGUAGE_MODEL=lm_studio/gemma-3-12b-it # Or openai/gpt-4o-mini 19 | TRIAGE_CLASSIFIER_VERSION=v4 # v0-v5 available 20 | ``` 21 | 22 | ## Classifier Versions 23 | - **v0**: Basic prompt-based 24 | - **v1**: Enhanced prompt with examples 25 | - **v2**: DSPy optimized few-shot 26 | - **v3**: Baseline few-shot with training 27 | - **v4**: Zero-shot COPRO optimized (default) 28 | - **v5**: Attention-based neural classifier 29 | 30 | ## Training 31 | ```bash 32 | make train-triage-classifier-v3 # Baseline 33 | make train-triage-classifier-v5 # Attention-based 34 | make compile-triage-classifier-v4 # Optimize DSPy 35 | make train-triage-classifier-v6 # run fine-tuning via OpenAI API 36 | make train-triage-classifier-v7 # run parameter efficient fine-tuning locally 37 | ``` 38 | 39 | ## Testing 40 | ```bash 41 | make test-triage-agent 42 | make test-triage-classifier-v4 # Test specific version 43 | ``` -------------------------------------------------------------------------------- /demo/agents/triage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/attention_net/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/attention_net/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/baseline_model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/baseline_model/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/baseline_model/metrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.metrics import roc_auc_score 3 | 4 | 5 | def compute_f1_score(y_true: np.array, y_pred: np.array, n_classes: int) -> float: 6 | """ 7 | Compute the F1 score for a multi-class classification problem. 8 | 9 | Args: 10 | y_true: True labels. 11 | y_pred: Predicted labels. 12 | n_classes: Number of classes. 13 | 14 | Returns: 15 | f1_score: F1 score. 16 | """ 17 | # Convert to binary labels 18 | y_true_binary = np.eye(n_classes)[y_true] 19 | y_pred_binary = np.eye(n_classes)[y_pred.argmax(axis=1)] 20 | 21 | # Compute precision and recall 22 | tp = np.sum(y_true_binary * y_pred_binary, axis=0) 23 | fp = np.sum((1 - y_true_binary) * y_pred_binary, axis=0) 24 | fn = np.sum(y_true_binary * (1 - y_pred_binary), axis=0) 25 | 26 | precision = tp / (tp + fp + 1e-10) 27 | recall = tp / (tp + fn + 1e-10) 28 | 29 | # Compute F1 score 30 | f1_score = 2 * (precision * recall) / (precision + recall + 1e-10) 31 | return np.mean(f1_score) 32 | 33 | 34 | def compute_roc_auc(y_true: np.array, y_pred: np.array) -> float: 35 | """ 36 | Macro-averaged One-vs-Rest ROC AUC score for multi-class classification. 37 | 38 | Args: 39 | y_true: True labels. 40 | y_pred: Predicted labels. 41 | n_classes: Number of classes. 42 | 43 | Returns: 44 | auc: AUC score. 45 | """ 46 | # Compute AUC 47 | auc = roc_auc_score(y_true, y_pred, average="macro", multi_class="ovr") 48 | return auc 49 | -------------------------------------------------------------------------------- /demo/agents/triage/classifier_v6/README.md: -------------------------------------------------------------------------------- 1 | # Classifier V6 - OpenAI Fine-tuned 2 | 3 | Fine-tuned GPT-4o-mini for triage classification using OpenAI's fine-tuning API. 4 | 5 | ## Benefits 6 | 7 | **Performance** 8 | - Higher accuracy on domain-specific triage decisions 9 | - More consistent classification behavior 10 | - Specialized knowledge of agent roles and routing 11 | 12 | **Efficiency** 13 | - Shorter prompts (knowledge stored in model weights) 14 | - Reduced token usage per classification 15 | - Faster inference without complex instructions 16 | 17 | **Production** 18 | - No prompt engineering required 19 | - Reliable behavior at scale 20 | - Less maintenance overhead 21 | 22 | ## Setup 23 | 24 | ```bash 25 | make train-triage-classifier-v6 26 | export TRIAGE_CLASSIFIER_VERSION="v6" 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```python 32 | from agents.triage.classifier_v6.classifier_v6 import classifier_v6 33 | 34 | result = classifier_v6(chat_history="User: I need help with my claim") 35 | ``` 36 | 37 | ## Training Options 38 | 39 | ```bash 40 | # Demo (20 examples) 41 | make train-triage-classifier-v6 42 | 43 | # Custom size 44 | FINETUNE_SAMPLE_SIZE=100 make train-triage-classifier-v6 45 | 46 | # Full dataset 47 | FINETUNE_SAMPLE_SIZE=-1 make train-triage-classifier-v6 48 | ``` 49 | 50 | ## Testing 51 | 52 | ```bash 53 | make test-triage-classifier-v6 54 | ``` -------------------------------------------------------------------------------- /demo/agents/triage/classifier_v6/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/classifier_v6/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/classifier_v6/data_utils.py: -------------------------------------------------------------------------------- 1 | """Data utilities for classifier v6.""" 2 | 3 | from typing import List 4 | 5 | import dspy 6 | 7 | from agents.triage.shared.data_utils import ( 8 | create_examples as _create_training_examples, 9 | ) 10 | 11 | 12 | def create_training_examples(sample_size: int = 20, seed: int = 42) -> List[dspy.Example]: 13 | """Create training examples for v6 classifier with default sample size of 20. 14 | 15 | Args: 16 | sample_size: Number of examples to sample (default: 20 for cost-effective OpenAI fine-tuning) 17 | seed: Random seed for reproducible sampling 18 | 19 | Returns: 20 | List of DSPy examples for training 21 | """ 22 | return _create_training_examples(sample_size=sample_size, seed=seed) -------------------------------------------------------------------------------- /demo/agents/triage/classifier_v7/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/classifier_v7/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/classifier_v8/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/classifier_v8/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/classifier_v8/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import Field 2 | from pydantic_settings import BaseSettings, SettingsConfigDict 3 | 4 | 5 | class ClassifierV8Settings(BaseSettings): 6 | n_classes: int = Field(default=5) 7 | model_config = SettingsConfigDict( 8 | env_prefix="TRIAGE_V8_", 9 | env_file=".env", 10 | env_file_encoding='utf-8', 11 | case_sensitive=False, 12 | extra='ignore', 13 | protected_namespaces=('settings_',) 14 | ) 15 | 16 | # RoBERTa model configuration 17 | model_name: str = Field(default="roberta-base", description="RoBERTa base model from HuggingFace") 18 | 19 | # Specify device for model loading 20 | device: str = Field(default="mps", description="Device to load the model on (mps, cuda, cpu)") 21 | 22 | # Fine-tuning parameters 23 | train_sample_size: int = Field(default=-1, description="Number of training samples to use") 24 | eval_sample_size: int = Field(default=-1, description="Number of evaluation samples to use") 25 | learning_rate: float = Field(default=2e-4) 26 | num_epochs: int = Field(default=10) 27 | batch_size: int = Field(default=8) 28 | gradient_accumulation_steps: int = Field(default=2) 29 | 30 | # LoRA parameters 31 | lora_r: int = Field(default=16) 32 | lora_alpha: int = Field(default=32) 33 | lora_dropout: float = Field(default=0.1) 34 | lora_target_modules: list = Field(default_factory=lambda: ["query", "value"]) 35 | 36 | # Model paths 37 | output_dir: str = Field(default="./models/roberta-triage-v8") -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/.env.example: -------------------------------------------------------------------------------- 1 | # Example environment variables for Docker deployment 2 | # You need at least one of these API keys 3 | OPENAI_API_KEY=your_openai_key_here 4 | GEMINI_API_KEY=your_gemini_key_here 5 | ANTHROPIC_API_KEY=your_anthropic_key_here 6 | 7 | # Database connection for Docker 8 | DATABASE_URL=postgresql://postgres:postgres@db:5432/triage_db 9 | 10 | # Application settings 11 | SECRET_KEY=development_secret_key 12 | DEBUG=true 13 | MODEL=openai/gpt-4o-mini 14 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.11-slim 2 | 3 | WORKDIR /app 4 | 5 | # Install dependencies 6 | COPY pyproject.toml . 7 | COPY uv.lock . 8 | 9 | # Install system dependencies 10 | RUN apt-get update && \ 11 | apt-get install -y --no-install-recommends gcc libpq-dev && \ 12 | apt-get clean && \ 13 | rm -rf /var/lib/apt/lists/* 14 | 15 | # Copy source code 16 | COPY src/ /app/src/ 17 | 18 | # Install application in development mode 19 | RUN pip install --no-cache-dir --upgrade pip && \ 20 | pip install --no-cache-dir -e . 21 | 22 | USER 1000 23 | 24 | # Run the application 25 | CMD ["triage-server", "--reload"] -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/dev_webserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Development script for running the webserver directly. 4 | For production use, install the package and use the `triage-server` command. 5 | """ 6 | 7 | import argparse 8 | import os 9 | import sys 10 | 11 | import uvicorn 12 | from dotenv import load_dotenv 13 | 14 | # Add src directory to path 15 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "."))) 16 | 17 | if __name__ == "__main__": 18 | # Load environment variables 19 | load_dotenv() 20 | 21 | # Parse command line arguments 22 | parser = argparse.ArgumentParser( 23 | description="Start the Triage Dataset Manager web server" 24 | ) 25 | parser.add_argument( 26 | "--host", 27 | type=str, 28 | default="0.0.0.0", 29 | help="Host to bind the server to (default: 0.0.0.0)", 30 | ) 31 | parser.add_argument( 32 | "--port", 33 | type=int, 34 | default=int(os.getenv("PORT", "8000")), 35 | help="Port to bind the server to (default: 8000 or PORT env var)", 36 | ) 37 | 38 | args = parser.parse_args() 39 | 40 | print(f"Starting development server on {args.host}:{args.port}...") 41 | uvicorn.run( 42 | "src.triage_webserver.app:app", host=args.host, port=args.port, reload=True 43 | ) 44 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: postgres:16-alpine 4 | restart: always 5 | environment: 6 | POSTGRES_USER: postgres 7 | POSTGRES_PASSWORD: postgres 8 | POSTGRES_DB: triage_db 9 | ports: 10 | - "5432:5432" 11 | volumes: 12 | - postgres_data:/var/lib/postgresql/data 13 | healthcheck: 14 | test: ["CMD-SHELL", "pg_isready -U postgres"] 15 | interval: 5s 16 | timeout: 5s 17 | retries: 5 18 | start_period: 10s 19 | 20 | webapp: 21 | build: 22 | context: . 23 | dockerfile: Dockerfile 24 | restart: always 25 | depends_on: 26 | db: 27 | condition: service_healthy 28 | environment: 29 | DATABASE_URL: postgresql://postgres:postgres@db:5432/triage_db 30 | MODEL: openai/gpt-4o-mini 31 | SECRET_KEY: ${SECRET_KEY:-development_secret_key} 32 | DEBUG: ${DEBUG:-true} 33 | OPENAI_API_KEY: ${OPENAI_API_KEY:-} 34 | ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} 35 | GEMINI_API_KEY: ${GEMINI_API_KEY:-} 36 | ports: 37 | - "8000:8000" 38 | volumes: 39 | - ./src:/app/src 40 | command: ["triage-server", "--host", "0.0.0.0", "--port", "8000", "--reload"] 41 | 42 | volumes: 43 | postgres_data: -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_agent_dataset/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/data_sets/synthetic/src/triage_agent_dataset/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_agent_dataset/config.py: -------------------------------------------------------------------------------- 1 | from pydantic_settings import BaseSettings 2 | 3 | 4 | class AppConfig(BaseSettings): 5 | TOTAL_TARGET: int = 100 6 | AGENT_DISTRIBUTION: dict = { 7 | "BillingAgent": 0.3, 8 | "PolicyAgent": 0.2, 9 | "ClaimsAgent": 0.25, 10 | "EscalationAgent": 0.15, 11 | "ChattyAgent": 0.1, 12 | } 13 | SPECIAL_CASE_DISTRIBUTION: dict = { 14 | "none": 0.5, 15 | "edge_case": 0.1, 16 | "cross_domain": 0.1, 17 | "language_switch": 0.1, 18 | "short_query": 0.05, 19 | "complex_query": 0.05, 20 | "small_talk": 0.05, 21 | "angry_customer": 0.025, 22 | "technical_error": 0.025, 23 | } 24 | MODEL: str = "openai/gpt-4o-mini" 25 | 26 | class Config: 27 | env_prefix = "" 28 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_agent_dataset/models.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import Optional 3 | 4 | from pydantic import BaseModel 5 | 6 | 7 | class Agents(str, Enum): 8 | BILLING = "BillingAgent" 9 | POLICY = "PolicyAgent" 10 | CLAIMS = "ClaimsAgent" 11 | ESCALATION = "EscalationAgent" 12 | CHATTY = "ChattyAgent" 13 | 14 | 15 | class SpecialCaseType(str, Enum): 16 | EDGE_CASE = "edge_case" 17 | CROSS_DOMAIN = "cross_domain" 18 | LANGUAGE_SWITCH = "language_switch" 19 | SHORT_QUERY = "short_query" 20 | COMPLEX_QUERY = "complex_query" 21 | SMALL_TALK = "small_talk" 22 | ANGRY_CUSTOMER = "angry_customer" 23 | TECHNICAL_ERROR = "technical_error" 24 | 25 | 26 | class ConversationExample(BaseModel): 27 | conversation: str 28 | target_agent: str 29 | turns: int 30 | temperature: float 31 | index_batch: int 32 | total_batch: int 33 | special_case: Optional[str] = None 34 | model: str 35 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/data_sets/synthetic/src/triage_webserver/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | 4 | import uvicorn 5 | from dotenv import load_dotenv 6 | 7 | 8 | def main(): 9 | """ 10 | Main entry point for the triage-server command 11 | """ 12 | # Load environment variables 13 | load_dotenv() 14 | 15 | # Parse command line arguments 16 | parser = argparse.ArgumentParser( 17 | description="Start the Triage Dataset Manager web server" 18 | ) 19 | parser.add_argument( 20 | "--host", 21 | type=str, 22 | default="0.0.0.0", 23 | help="Host to bind the server to (default: 0.0.0.0)", 24 | ) 25 | parser.add_argument( 26 | "--port", 27 | type=int, 28 | default=int(os.getenv("PORT", "8000")), 29 | help="Port to bind the server to (default: 8000 or PORT env var)", 30 | ) 31 | parser.add_argument( 32 | "--reload", action="store_true", help="Enable auto-reload for development" 33 | ) 34 | 35 | args = parser.parse_args() 36 | 37 | # Run the application 38 | uvicorn.run( 39 | "triage_webserver.app:app", host=args.host, port=args.port, reload=args.reload 40 | ) 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/config.py: -------------------------------------------------------------------------------- 1 | from pydantic_settings import BaseSettings 2 | 3 | 4 | class WebServerConfig(BaseSettings): 5 | DATABASE_URL: str = "postgresql://postgres:postgres@db:5432/triage_db" 6 | SECRET_KEY: str = "development_secret_key" 7 | MODEL: str = "openai/gpt-4o-mini" 8 | DEBUG: bool = True 9 | 10 | class Config: 11 | env_prefix = "" 12 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/database/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/data_sets/synthetic/src/triage_webserver/database/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/database/base.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.ext.declarative import declarative_base 2 | 3 | # Create a single base class for all models 4 | Base = declarative_base() 5 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/data_sets/synthetic/src/triage_webserver/models/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/routes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/data_sets/synthetic/src/triage_webserver/routes/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/schemas/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/data_sets/synthetic/src/triage_webserver/schemas/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/schemas/dataset_schemas.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Dict, List, Optional 3 | 4 | from pydantic import BaseModel 5 | 6 | 7 | class DatasetBase(BaseModel): 8 | name: str 9 | description: Optional[str] = None 10 | model: Optional[str] = None 11 | 12 | 13 | class DatasetCreate(DatasetBase): 14 | total_target: int = 100 15 | agent_distribution: Optional[Dict[str, float]] = None 16 | special_case_distribution: Optional[Dict[str, float]] = None 17 | temperatures: List[float] = [0.7, 0.8, 0.9] 18 | turns: List[int] = [1, 3, 5] 19 | 20 | 21 | class DatasetResponse(DatasetBase): 22 | id: int 23 | total_examples: int 24 | created_at: datetime 25 | updated_at: datetime 26 | 27 | model_config = {"from_attributes": True} 28 | 29 | 30 | class DatasetList(BaseModel): 31 | datasets: List[DatasetResponse] 32 | total: int 33 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/schemas/example_schemas.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import List, Optional 3 | 4 | from pydantic import BaseModel 5 | 6 | 7 | class ExampleBase(BaseModel): 8 | conversation: str 9 | target_agent: str 10 | turns: int 11 | temperature: float 12 | special_case: Optional[str] = None 13 | 14 | 15 | class ExampleCreate(ExampleBase): 16 | dataset_id: int 17 | index_batch: Optional[int] = None 18 | total_batch: Optional[int] = None 19 | 20 | 21 | class ExampleUpdate(BaseModel): 22 | conversation: Optional[str] = None 23 | target_agent: Optional[str] = None 24 | turns: Optional[int] = None 25 | temperature: Optional[float] = None 26 | special_case: Optional[str] = None 27 | 28 | 29 | class ExampleResponse(ExampleBase): 30 | id: int 31 | dataset_id: int 32 | index_batch: Optional[int] 33 | total_batch: Optional[int] 34 | created_at: datetime 35 | updated_at: datetime 36 | 37 | model_config = {"from_attributes": True} 38 | 39 | 40 | class ExampleList(BaseModel): 41 | examples: List[ExampleResponse] 42 | total: int 43 | -------------------------------------------------------------------------------- /demo/agents/triage/data_sets/synthetic/src/triage_webserver/services/__init__.py: -------------------------------------------------------------------------------- 1 | # Initialize the services package 2 | -------------------------------------------------------------------------------- /demo/agents/triage/dspy_modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/dspy_modules/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/dspy_modules/classifier_v1.py: -------------------------------------------------------------------------------- 1 | import dspy 2 | from dotenv import load_dotenv 3 | 4 | from agents.triage.config import Settings 5 | from agents.triage.models import ClassifierMetrics, TargetAgent 6 | from libraries.ml.dspy.language_model import dspy_set_language_model 7 | 8 | load_dotenv() 9 | 10 | settings = Settings() 11 | 12 | lm = dspy_set_language_model(settings) 13 | 14 | 15 | class AgentClassificationSignature(dspy.Signature): 16 | def __init__(self, chat_history: str): 17 | super().__init__(chat_history=chat_history) 18 | self.metrics: ClassifierMetrics 19 | 20 | chat_history: str = dspy.InputField() 21 | target_agent: TargetAgent = dspy.OutputField() 22 | 23 | 24 | classifier_v1_program = dspy.Predict(signature=AgentClassificationSignature) 25 | 26 | 27 | def classifier_v1(chat_history: str) -> AgentClassificationSignature: 28 | result = classifier_v1_program(chat_history=chat_history) 29 | result.metrics = ClassifierMetrics( 30 | total_tokens=lm.total_tokens, 31 | prompt_tokens=lm.prompt_tokens, 32 | completion_tokens=lm.completion_tokens, 33 | latency_ms=lm.latency_ms, 34 | ) 35 | return result 36 | 37 | 38 | if __name__ == "__main__": 39 | res = classifier_v1( 40 | chat_history="User: hello!", 41 | ) 42 | print(res.target_agent) 43 | print(res.metrics) 44 | -------------------------------------------------------------------------------- /demo/agents/triage/dspy_modules/classifier_v2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/dspy_modules/classifier_v2/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/dspy_modules/classifier_v4/__init__.py: -------------------------------------------------------------------------------- 1 | from .classifier_v4 import classifier_v4 as classifier_v4 -------------------------------------------------------------------------------- /demo/agents/triage/dspy_modules/evaluation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/dspy_modules/evaluation/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from eggai import eggai_main 4 | from eggai.transport import eggai_set_default_transport 5 | 6 | from agents.triage.config import settings 7 | from libraries.communication.transport import create_kafka_transport 8 | from libraries.ml.dspy.language_model import dspy_set_language_model 9 | from libraries.observability.logger import get_console_logger 10 | from libraries.observability.tracing import init_telemetry 11 | from libraries.observability.tracing.init_metrics import init_token_metrics 12 | 13 | eggai_set_default_transport( 14 | lambda: create_kafka_transport( 15 | bootstrap_servers=settings.kafka_bootstrap_servers, 16 | ssl_cert=settings.kafka_ca_content, 17 | ) 18 | ) 19 | init_token_metrics(port=settings.prometheus_metrics_port, application_name=settings.app_name) 20 | 21 | from agents.triage.agent import triage_agent 22 | 23 | logger = get_console_logger("triage_agent") 24 | 25 | 26 | @eggai_main 27 | async def main(): 28 | 29 | logger.info(f"Starting {settings.app_name}") 30 | 31 | init_telemetry(app_name=settings.app_name, endpoint=settings.otel_endpoint) 32 | logger.info(f"Telemetry initialized for {settings.app_name}") 33 | dspy_set_language_model(settings) 34 | 35 | await triage_agent.start() 36 | logger.info(f"{settings.app_name} started successfully") 37 | 38 | await asyncio.Future() 39 | 40 | 41 | if __name__ == "__main__": 42 | try: 43 | asyncio.run(main()) 44 | except KeyboardInterrupt: 45 | logger.info("Shutting down triage agent") 46 | except Exception as e: 47 | logger.error(f"Error in main: {e}", exc_info=True) 48 | -------------------------------------------------------------------------------- /demo/agents/triage/model_checkpoints/attention_net.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/model_checkpoints/attention_net.pth -------------------------------------------------------------------------------- /demo/agents/triage/model_checkpoints/fewshot_baseline_n_all.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/model_checkpoints/fewshot_baseline_n_all.pkl -------------------------------------------------------------------------------- /demo/agents/triage/shared/__init__.py: -------------------------------------------------------------------------------- 1 | """Shared utilities for triage classifiers.""" -------------------------------------------------------------------------------- /demo/agents/triage/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/demo/agents/triage/tests/__init__.py -------------------------------------------------------------------------------- /demo/agents/triage/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import pytest 4 | 5 | 6 | @pytest.fixture(scope="session") 7 | def event_loop(): 8 | """Ensure a fresh event loop for the test session to avoid 'RuntimeError: Event loop is closed'.""" 9 | loop = asyncio.new_event_loop() 10 | asyncio.set_event_loop(loop) 11 | yield loop 12 | loop.close() 13 | -------------------------------------------------------------------------------- /demo/agents/triage/tests/test_agent_utils.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from agents.triage.agent import ( 4 | _CLASSIFIER_PATHS, 5 | build_conversation_string, 6 | get_current_classifier, 7 | ) 8 | from agents.triage.config import settings 9 | 10 | 11 | def test_build_conversation_string_empty(): 12 | # No messages yields empty string 13 | assert build_conversation_string([]) == "" 14 | 15 | 16 | def test_build_conversation_string_basic(): 17 | msgs = [ 18 | {"agent": "User", "content": "Hello"}, 19 | {"agent": "Bot", "content": "Hi there!"}, 20 | ] 21 | expected = "User: Hello\nBot: Hi there!\n" 22 | assert build_conversation_string(msgs) == expected 23 | 24 | 25 | def test_build_conversation_string_filters_empty_content(): 26 | msgs = [ 27 | {"agent": "User", "content": ""}, 28 | {"agent": "Bot", "content": "Response"}, 29 | ] 30 | expected = "Bot: Response\n" 31 | assert build_conversation_string(msgs) == expected 32 | 33 | 34 | @pytest.mark.parametrize("version,module_fn", list(_CLASSIFIER_PATHS.items())) 35 | def test_get_current_classifier_valid(monkeypatch, version, module_fn): 36 | # Ensure get_current_classifier returns a callable for each supported version 37 | monkeypatch.setattr(settings, "classifier_version", version) 38 | fn = get_current_classifier() 39 | assert callable(fn) 40 | 41 | 42 | def test_get_current_classifier_invalid(monkeypatch): 43 | # Unsupported version should raise ValueError 44 | monkeypatch.setattr(settings, "classifier_version", "nonexistent") 45 | with pytest.raises(ValueError): 46 | get_current_classifier() -------------------------------------------------------------------------------- /demo/dev-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest-asyncio==0.24.0 2 | pytest==8.3.4 3 | ruff -------------------------------------------------------------------------------- /demo/docker-compose-lmstudio.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | lmstudio: 3 | image: ghcr.io/eggai-tech/lm-studio:gemma-3-12B-it-qat-GGUF-1.0 4 | environment: 5 | MODEL_NAME: gemma-3-12B-it-qat 6 | MODEL_PATH: /gemma-3-12B-it-QAT-Q4_0.gguf 7 | CONTEXT_LENGTH: 32768 8 | ports: 9 | - "1234:1234" 10 | networks: 11 | - eggai-example-network 12 | -------------------------------------------------------------------------------- /demo/dockerConfig/development-sql.yaml: -------------------------------------------------------------------------------- 1 | limit.maxIDLength: 2 | - value: 255 3 | constraints: {} 4 | system.forceSearchAttributesCacheRefreshOnRead: 5 | - value: true # Dev setup only. Please don't turn this on in production. 6 | constraints: {} -------------------------------------------------------------------------------- /demo/dockerConfig/grafana-provisioning.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: 'default' 5 | orgId: 1 6 | folder: '' 7 | type: file 8 | disableDeletion: false 9 | updateIntervalSeconds: 10 10 | options: 11 | path: /var/lib/grafana/dashboards 12 | -------------------------------------------------------------------------------- /demo/dockerConfig/loki.yaml: -------------------------------------------------------------------------------- 1 | auth_enabled: false 2 | 3 | server: 4 | http_listen_port: 3100 5 | grpc_listen_port: 9096 6 | 7 | common: 8 | instance_addr: 0.0.0.0 9 | path_prefix: /tmp/loki 10 | storage: 11 | filesystem: 12 | chunks_directory: /tmp/loki/chunks 13 | rules_directory: /tmp/loki/rules 14 | replication_factor: 1 15 | ring: 16 | kvstore: 17 | store: inmemory 18 | 19 | limits_config: 20 | allow_structured_metadata: false 21 | 22 | query_range: 23 | results_cache: 24 | cache: 25 | embedded_cache: 26 | enabled: true 27 | max_size_mb: 100 28 | 29 | schema_config: 30 | configs: 31 | - from: 2020-10-24 32 | store: tsdb 33 | object_store: filesystem 34 | schema: v12 35 | index: 36 | prefix: index_ 37 | period: 24h 38 | -------------------------------------------------------------------------------- /demo/dockerConfig/otel-collector.yaml: -------------------------------------------------------------------------------- 1 | receivers: 2 | otlp: 3 | protocols: 4 | grpc: 5 | endpoint: 0.0.0.0:4317 6 | http: 7 | endpoint: 0.0.0.0:4318 8 | exporters: 9 | otlp: 10 | endpoint: tempo:4317 11 | tls: 12 | insecure: true 13 | logging: 14 | verbosity: detailed 15 | prometheus: 16 | endpoint: 0.0.0.0:9464 17 | service: 18 | pipelines: 19 | traces: 20 | receivers: [otlp] 21 | exporters: [otlp] 22 | metrics: 23 | receivers: [ otlp ] 24 | exporters: [ prometheus,logging ] -------------------------------------------------------------------------------- /demo/dockerConfig/prometheus.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | 5 | scrape_configs: 6 | - job_name: 'prometheus' 7 | static_configs: 8 | - targets: [ 'localhost:9090' ] 9 | 10 | - job_name: 'tempo' 11 | static_configs: 12 | - targets: [ 'tempo:3200' ] 13 | 14 | - job_name: 'otel-collector' 15 | scrape_interval: 5s 16 | static_configs: 17 | - targets: [ 'otel-collector:9464' ] 18 | 19 | - job_name: 'eggai-triage-agent' 20 | scrape_interval: 5s 21 | static_configs: 22 | - targets: [ 'host.docker.internal:9091' ] 23 | 24 | - job_name: 'eggai-claims-agent' 25 | scrape_interval: 5s 26 | static_configs: 27 | - targets: [ 'host.docker.internal:9092' ] 28 | 29 | - job_name: 'eggai-policies-agent' 30 | scrape_interval: 5s 31 | static_configs: 32 | - targets: [ 'host.docker.internal:9093' ] 33 | 34 | - job_name: 'eggai-escalation-agent' 35 | scrape_interval: 5s 36 | static_configs: 37 | - targets: [ 'host.docker.internal:9094' ] 38 | 39 | - job_name: 'eggai-billing-agent' 40 | scrape_interval: 5s 41 | static_configs: 42 | - targets: [ 'host.docker.internal:9095' ] 43 | 44 | - job_name: 'eggai-audit-agent' 45 | scrape_interval: 5s 46 | static_configs: 47 | - targets: [ 'host.docker.internal:9096' ] 48 | 49 | - job_name: 'eggai-frontend-agent' 50 | scrape_interval: 5s 51 | static_configs: 52 | - targets: [ 'host.docker.internal:9097' ] 53 | -------------------------------------------------------------------------------- /demo/docs/agents-overview.md: -------------------------------------------------------------------------------- 1 | # Agent Capabilities Overview 2 | 3 | ## Agent Roles 4 | 5 | | Agent | Purpose | Key Capabilities | 6 | |-------|---------|------------------| 7 | | **Frontend** | Web UI & WebSocket gateway | Serves chat interface, manages connections, handles reconnections | 8 | | **Triage** | Request routing | Classifies intent (ML), routes to specialists, handles greetings | 9 | | **Billing** | Payment & premiums | Retrieves/updates billing info, payment dates, amounts | 10 | | **Claims** | Claims processing | Files new claims, checks status, updates info, estimates | 11 | | **Policies** | Coverage & documents | Personal policy data, RAG document search, coverage Q&A | 12 | | **Escalation** | Complex issues | Multi-step workflows, support tickets, complaints | 13 | | **Audit** | Compliance tracking | Logs all messages, categorizes by domain, audit trail | 14 | 15 | ## Message Flow 16 | 17 | ``` 18 | User → Frontend → Triage → Specialized Agent → Response → User 19 | ↓ 20 | Audit (logs all interactions) 21 | ``` 22 | 23 | ## Agent Communication 24 | 25 | - **Channels**: `human` (user messages), `agents` (routed requests), `audit_logs` (compliance) 26 | - **Pattern**: Event-driven pub/sub via Redpanda 27 | - **Scaling**: Each agent runs independently, horizontally scalable 28 | 29 | ## Running Agents 30 | 31 | ```bash 32 | # Start all agents 33 | make start-all 34 | 35 | # Individual agents 36 | make start-triage 37 | make start-billing 38 | # etc. 39 | ``` 40 | 41 | --- 42 | 43 | **Previous:** [System Architecture](system-architecture.md) | **Next:** [Multi-Agent Communication](multi-agent-communication.md) -------------------------------------------------------------------------------- /demo/helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /demo/helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: eggai-multi-agent-chat 3 | description: A Helm chart for EggAI multi-agent human chat example application 4 | 5 | type: application 6 | 7 | version: "0.5.7" 8 | appVersion: "0.1.0" 9 | -------------------------------------------------------------------------------- /demo/helm/templates/monitoring.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.monitoring.enabled }} 2 | {{- range $name,$value := .Values.agents }} 3 | --- 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: {{ include "eggai-multi-agent-chat.fullname" $ }}-{{ lower $name }}-metrics 8 | labels: 9 | {{- include "eggai-multi-agent-chat.labels" $ | nindent 4 }} 10 | app.kubernetes.io/component: monitoring 11 | egg-ai.com/agent: {{ $name }} 12 | spec: 13 | type: ClusterIP 14 | ports: 15 | - port: {{ $.Values.monitoring.port }} 16 | targetPort: metrics 17 | protocol: TCP 18 | name: metrics 19 | selector: 20 | {{- include "eggai-multi-agent-chat.selectorLabels" $ | nindent 4 }} 21 | egg-ai.com/agent: {{ $name }} 22 | --- 23 | apiVersion: monitoring.coreos.com/v1 24 | kind: ServiceMonitor 25 | metadata: 26 | name: {{ include "eggai-multi-agent-chat.fullname" $ }}-{{ lower $name }} 27 | labels: 28 | {{- include "eggai-multi-agent-chat.labels" $ | nindent 4 }} 29 | spec: 30 | endpoints: 31 | - honorLabels: true 32 | interval: {{ $.Values.monitoring.serviceMonitor.interval | default "30s" }} 33 | path: /metrics 34 | port: metrics 35 | scheme: http 36 | scrapeTimeout: {{ $.Values.monitoring.serviceMonitor.scrapeTimeout | default "10s" }} 37 | selector: 38 | matchLabels: 39 | {{- include "eggai-multi-agent-chat.selectorLabels" $ | nindent 6 }} 40 | app.kubernetes.io/component: monitoring 41 | egg-ai.com/agent: {{ $name }} 42 | {{- end }} 43 | {{- end }} 44 | -------------------------------------------------------------------------------- /demo/helm/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "eggai-multi-agent-chat.fullname" . }} 5 | labels: 6 | {{- include "eggai-multi-agent-chat.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "eggai-multi-agent-chat.selectorLabels" . | nindent 4 }} 16 | egg-ai.com/agent: frontend 17 | -------------------------------------------------------------------------------- /demo/helm/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "eggai-multi-agent-chat.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "eggai-multi-agent-chat.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | automountServiceAccountToken: false 11 | containers: 12 | - name: wget 13 | image: busybox 14 | command: ['wget'] 15 | args: ['{{ include "eggai-multi-agent-chat.fullname" . }}:{{ .Values.service.port }}'] 16 | resources: 17 | limits: 18 | cpu: "250m" 19 | memory: "512Mi" 20 | requests: 21 | cpu: "100m" 22 | memory: "128Mi" 23 | ephemeralStorage: "2Gi" 24 | restartPolicy: Never 25 | -------------------------------------------------------------------------------- /demo/helm/values.yaml: -------------------------------------------------------------------------------- 1 | agents: 2 | audit: 3 | enabled: true 4 | replicaCount: 1 5 | environment: [] 6 | billing: 7 | enabled: true 8 | replicaCount: 1 9 | environment: [] 10 | claims: 11 | enabled: true 12 | replicaCount: 1 13 | environment: [] 14 | escalation: 15 | enabled: true 16 | replicaCount: 1 17 | environment: [] 18 | frontend: 19 | enabled: true 20 | replicaCount: 1 21 | environment: [] 22 | policiesDocumentIngestion: 23 | enabled: true 24 | replicaCount: 1 25 | environment: [] 26 | policies: 27 | enabled: true 28 | replicaCount: 1 29 | environment: [] 30 | triage: 31 | enabled: true 32 | replicaCount: 1 33 | environment: [] 34 | 35 | image: 36 | repository: ghcr.io/eggai-tech/multi-agent-human-chat 37 | pullPolicy: IfNotPresent 38 | tag: latest 39 | 40 | imagePullSecrets: [] 41 | nameOverride: "" 42 | fullnameOverride: "" 43 | 44 | resources: 45 | limits: 46 | cpu: "250m" 47 | memory: "512Mi" 48 | requests: 49 | cpu: "100m" 50 | memory: "128Mi" 51 | ephemeral-storage: "10Gi" 52 | 53 | cacheVolumeSize: "10Gi" 54 | 55 | podAnnotations: {} 56 | 57 | podSecurityContext: {} 58 | 59 | securityContext: {} 60 | 61 | service: 62 | type: ClusterIP 63 | port: 8000 64 | 65 | monitoring: 66 | enabled: true 67 | port: 9000 68 | serviceMonitor: 69 | interval: 30s 70 | scrapeTimeout: 10s 71 | 72 | nodeSelector: {} 73 | tolerations: [] 74 | 75 | gpuNodeSelector: {} 76 | gpuTolerations: [] 77 | -------------------------------------------------------------------------------- /demo/libraries/README.md: -------------------------------------------------------------------------------- 1 | # Libraries 2 | 3 | Shared utilities and infrastructure for EggAI agents. 4 | 5 | ## Structure 6 | 7 | ### Core (`core/`) 8 | - `BaseAgentConfig` - Base configuration class 9 | - `ModelConfig`, `ModelResult` - ML data models 10 | - System patches for DSPy tracking 11 | 12 | ### Communication (`communication/`) 13 | - `channels.py` - Channel configuration with namespacing 14 | - `messaging.py` - Type-safe message subscription 15 | - `transport.py` - Kafka transport with SSL 16 | - `protocol/` - Message types and enums 17 | 18 | ### ML (`ml/`) 19 | - `device.py` - PyTorch device utilities 20 | - `mlflow.py` - Model artifact management 21 | - `dspy/` - Language model wrapper and optimizer 22 | 23 | ### Observability (`observability/`) 24 | - `logger/` - Structured logging 25 | - `tracing/` - OpenTelemetry, metrics, pricing 26 | 27 | ### Integrations (`integrations/`) 28 | - `vespa/` - Document search client 29 | 30 | ### Testing (`testing/`) 31 | - `utils/` - Test helpers 32 | - `tests/` - Unit tests 33 | 34 | ## Usage 35 | 36 | ```python 37 | from libraries.communication import channels, subscribe 38 | from libraries.core import BaseAgentConfig 39 | from libraries.observability import get_console_logger 40 | from libraries.ml.dspy import dspy_set_language_model 41 | ``` -------------------------------------------------------------------------------- /demo/libraries/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | EggAI Libraries - Organized utilities for building AI agents. 3 | 4 | Structure: 5 | - core/: Core utilities and base classes 6 | - communication/: Messaging, channels, and transport 7 | - ml/: Machine learning utilities and DSPy integration 8 | - observability/: Logging, tracing, and monitoring 9 | - integrations/: External service integrations 10 | - testing/: Test utilities and unit tests 11 | 12 | Import from specific modules: 13 | from libraries.communication import channels, subscribe 14 | from libraries.core import BaseAgentConfig 15 | from libraries.observability import get_console_logger 16 | """ 17 | 18 | from libraries.core.patches import patch_usage_tracker 19 | 20 | # Apply patches 21 | patch_usage_tracker() 22 | -------------------------------------------------------------------------------- /demo/libraries/communication/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Communication infrastructure for EggAI agents. 3 | 4 | This module provides messaging, channels, and transport functionality. 5 | """ 6 | 7 | from .channels import channels 8 | from .messaging import subscribe 9 | from .transport import create_kafka_transport 10 | 11 | __all__ = [ 12 | "channels", 13 | "subscribe", 14 | "create_kafka_transport", 15 | ] -------------------------------------------------------------------------------- /demo/libraries/communication/transport.py: -------------------------------------------------------------------------------- 1 | import ssl 2 | from typing import Optional 3 | 4 | from eggai.transport import KafkaTransport 5 | from faststream.kafka import KafkaBroker 6 | from faststream.security import BaseSecurity 7 | 8 | 9 | def create_kafka_transport( 10 | bootstrap_servers: str, ssl_cert: Optional[str] = None 11 | ) -> KafkaTransport: 12 | """ 13 | Create a KafkaTransport instance with SSL support when certificate is provided. 14 | 15 | Args: 16 | bootstrap_servers: Comma-separated list of Kafka bootstrap servers 17 | ssl_cert: SSL certificate content as a string (optional) 18 | 19 | Returns: 20 | KafkaTransport: Configured Kafka transport instance 21 | """ 22 | # Parse bootstrap servers 23 | servers_list = bootstrap_servers.split(",") 24 | 25 | # Use SSL if certificate is provided 26 | if ssl_cert and ssl_cert.strip(): 27 | ssl_context = ssl.create_default_context() 28 | ssl_context.check_hostname = False 29 | ssl_context.verify_mode = ssl.CERT_NONE 30 | 31 | # Load the certificate directly from the string 32 | ssl_context.load_verify_locations(cadata=ssl_cert) 33 | 34 | # Create broker with SSL 35 | broker = KafkaBroker( 36 | bootstrap_servers=servers_list, 37 | security=BaseSecurity(use_ssl=True, ssl_context=ssl_context), 38 | ) 39 | else: 40 | # Create broker without SSL 41 | broker = KafkaBroker(bootstrap_servers=servers_list) 42 | 43 | return KafkaTransport(broker=broker) 44 | -------------------------------------------------------------------------------- /demo/libraries/core/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Core utilities and base classes for EggAI agents. 3 | 4 | This module provides fundamental building blocks used across all agents. 5 | """ 6 | 7 | from .config import BaseAgentConfig 8 | from .models import ModelConfig, ModelResult 9 | from .patches import patch_usage_tracker 10 | 11 | __all__ = [ 12 | "BaseAgentConfig", 13 | "ModelConfig", 14 | "ModelResult", 15 | "patch_usage_tracker", 16 | ] -------------------------------------------------------------------------------- /demo/libraries/core/patches.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | from libraries.observability.logger import get_console_logger 4 | 5 | logger = get_console_logger("libraries.patches") 6 | 7 | 8 | def patch_usage_tracker(): 9 | # FIXME: Patch the UsageTracker to handle nested dicts in usage entries 10 | def _merge_usage_entries(self, entry1, entry2) -> dict[str, dict[str, Any]]: 11 | # If one side is empty or None, just clone the other 12 | if not entry1: 13 | return dict(entry2 or {}) 14 | if not entry2: 15 | return dict(entry1 or {}) 16 | 17 | # Start with a shallow copy of entry2 18 | result = dict(entry2) 19 | 20 | for key, val1 in entry1.items(): 21 | val2 = result.get(key) 22 | 23 | # If either side is a dict, merge them recursively (treat None as {}) 24 | if isinstance(val1, dict) or isinstance(val2, dict): 25 | sub1 = val1 if isinstance(val1, dict) else {} 26 | sub2 = val2 if isinstance(val2, dict) else {} 27 | result[key] = self._merge_usage_entries(sub1, sub2) 28 | 29 | else: 30 | # Treat None or missing as zero, then sum 31 | num1 = val1 or 0 32 | num2 = val2 or 0 33 | result[key] = num1 + num2 34 | 35 | return result 36 | 37 | # Apply the patch 38 | from dspy.utils.usage_tracker import UsageTracker 39 | 40 | UsageTracker._merge_usage_entries = _merge_usage_entries 41 | logger.info("DSPY UsageTracker patched successfully") 42 | -------------------------------------------------------------------------------- /demo/libraries/integrations/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | External service integrations for EggAI agents. 3 | 4 | This module provides integrations with external services like Vespa. 5 | """ 6 | 7 | # Currently empty - integrations are imported directly from submodules 8 | __all__ = [] -------------------------------------------------------------------------------- /demo/libraries/integrations/vespa/__init__.py: -------------------------------------------------------------------------------- 1 | from .config import VespaConfig as VespaConfig 2 | from .schemas import DocumentMetadata as DocumentMetadata 3 | from .schemas import PolicyDocument as PolicyDocument 4 | from .vespa_client import VespaClient as VespaClient 5 | -------------------------------------------------------------------------------- /demo/libraries/ml/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Machine Learning utilities for EggAI agents. 3 | 4 | This module provides ML-related functionality including DSPy integration, 5 | device management, and MLflow utilities. 6 | """ 7 | 8 | from .device import get_device 9 | 10 | __all__ = [ 11 | "get_device", 12 | ] -------------------------------------------------------------------------------- /demo/libraries/ml/device.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | def get_device() -> str: 5 | """Get the optimal device for PyTorch operations.""" 6 | if torch.cuda.is_available(): 7 | return "cuda" 8 | if hasattr(torch.backends, "mps") and torch.backends.mps.is_available(): 9 | return "mps" 10 | if hasattr(torch, "xpu") and torch.xpu.is_available(): 11 | return "xpu" 12 | return "cpu" 13 | -------------------------------------------------------------------------------- /demo/libraries/ml/dspy/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | DSPy-specific utilities. 3 | 4 | This module provides DSPy language model integration and optimizers. 5 | """ 6 | 7 | from .language_model import TrackingLM, dspy_set_language_model 8 | from .optimizer import SIMBAOptimizer 9 | 10 | __all__ = [ 11 | "SIMBAOptimizer", 12 | "TrackingLM", 13 | "dspy_set_language_model", 14 | ] -------------------------------------------------------------------------------- /demo/libraries/ml/mlflow.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | import dotenv 4 | from mlflow import MlflowClient 5 | 6 | dotenv.load_dotenv() 7 | 8 | 9 | def find_model(model_name: str, version: str, artifact_path: str = "model") -> str: 10 | cache_path = Path(__file__).resolve().parents[1] / ".cache" 11 | cache_path.mkdir(parents=True, exist_ok=True) 12 | 13 | pickle_path = cache_path / model_name / version / artifact_path / "model.pkl" 14 | if pickle_path.exists(): 15 | return str(pickle_path) 16 | pytorch_path = ( 17 | cache_path / model_name / version / artifact_path / "data" / "model.pth" 18 | ) 19 | if pytorch_path.exists(): 20 | return str(pytorch_path) 21 | 22 | client = MlflowClient() 23 | mv = client.get_model_version(name=model_name, version=version) 24 | run_id = mv.run_id 25 | 26 | dest = cache_path / model_name / version 27 | dest.mkdir(parents=True, exist_ok=True) 28 | client.download_artifacts(run_id, artifact_path, dst_path=str(dest)) 29 | if pickle_path.exists(): 30 | return str(pickle_path) 31 | if pytorch_path.exists(): 32 | return str(pytorch_path) 33 | 34 | 35 | if __name__ == "__main__": 36 | print(find_model("attention_net_0.25_0.0002", version="1")) 37 | -------------------------------------------------------------------------------- /demo/libraries/observability/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Observability utilities for monitoring and debugging EggAI agents. 3 | 4 | This module provides logging, tracing, and metrics functionality. 5 | """ 6 | 7 | # Re-export commonly used functions for convenience 8 | from .logger import configure_logging, get_console_logger 9 | from .tracing import TracedMessage, create_tracer, init_telemetry, traced_handler 10 | 11 | __all__ = [ 12 | # Logging 13 | "configure_logging", 14 | "get_console_logger", 15 | # Tracing 16 | "TracedMessage", 17 | "create_tracer", 18 | "init_telemetry", 19 | "traced_handler", 20 | ] -------------------------------------------------------------------------------- /demo/libraries/observability/logger/__init__.py: -------------------------------------------------------------------------------- 1 | from .logger import configure_logging as configure_logging 2 | from .logger import get_console_logger as get_console_logger 3 | -------------------------------------------------------------------------------- /demo/libraries/observability/logger/config.py: -------------------------------------------------------------------------------- 1 | from dotenv import load_dotenv 2 | from pydantic import Field 3 | from pydantic_settings import BaseSettings, SettingsConfigDict 4 | 5 | # Load environment variables at module level 6 | load_dotenv() 7 | 8 | 9 | class Settings(BaseSettings): 10 | log_level: str = Field(default="INFO") 11 | log_format: str = Field( 12 | default="%(asctime)s %(levelname)s %(name)s %(filename)s %(lineno)d %(funcName)s %(message)s", 13 | env="LOG_FORMAT", 14 | ) 15 | 16 | # Logging formatter to use (json, standard, colored) 17 | log_formatter: str = Field(default="colored") 18 | 19 | # In which directories to automatically suppress certain loggers 20 | suppress_loggers: list[str] = Field( 21 | default=["httpx", "urllib3", "asyncio", "aiokafka"], env="SUPPRESS_LOGGERS" 22 | ) 23 | 24 | # Default suppression level (only apply warnings and above for suppressed loggers) 25 | suppress_level: str = Field(default="WARNING") 26 | 27 | model_config = SettingsConfigDict( 28 | env_prefix="LOGGER_", env_file=".env", env_ignore_empty=True, extra="ignore" 29 | ) 30 | 31 | 32 | settings = Settings() 33 | -------------------------------------------------------------------------------- /demo/libraries/observability/tracing/__init__.py: -------------------------------------------------------------------------------- 1 | from .dspy import TracedChainOfThought as TracedChainOfThought 2 | from .dspy import TracedReAct as TracedReAct 3 | from .dspy import traced_dspy_function as traced_dspy_function 4 | from .otel import create_tracer as create_tracer 5 | from .otel import format_span_as_traceparent as format_span_as_traceparent 6 | from .otel import init_telemetry as init_telemetry 7 | from .otel import safe_set_attribute as safe_set_attribute 8 | from .otel import traced_handler as traced_handler 9 | from .schemas import GenAIAttributes as GenAIAttributes 10 | from .schemas import TracedMessage as TracedMessage 11 | -------------------------------------------------------------------------------- /demo/libraries/observability/tracing/config.py: -------------------------------------------------------------------------------- 1 | from dotenv import load_dotenv 2 | from pydantic import Field 3 | from pydantic_settings import BaseSettings, SettingsConfigDict 4 | 5 | # Load environment variables at module level 6 | load_dotenv() 7 | 8 | 9 | class Settings(BaseSettings): 10 | # OpenTelemetry settings 11 | service_namespace: str = Field(default="eggai") 12 | otel_endpoint: str = Field(default="http://localhost:4318") 13 | otel_endpoint_insecure: bool = Field(default=True) 14 | otel_exporter_otlp_protocol: str = Field(default="http/protobuf") 15 | tracing_enabled: bool = Field(default=True) 16 | 17 | # Instrumentation configuration 18 | disabled_instrumentors: list[str] = Field(default=["langchain"]) 19 | 20 | # Sampling rate (1.0 = 100% of traces are sampled) 21 | sampling_rate: float = Field(default=1.0) 22 | 23 | model_config = SettingsConfigDict( 24 | env_prefix="TRACING_", env_file=".env", env_ignore_empty=True, extra="ignore" 25 | ) 26 | 27 | 28 | settings = Settings() 29 | -------------------------------------------------------------------------------- /demo/libraries/observability/tracing/schemas.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from typing import Dict, Optional 3 | 4 | from eggai.schemas import Message 5 | from pydantic import BaseModel, Field 6 | 7 | 8 | # TODO make traceparent required and remove default 9 | class TracedMessage(Message): 10 | 11 | traceparent: Optional[str] = Field( 12 | default=None, 13 | description="W3C trace context traceparent header (version-traceID-spanID-flags)", 14 | ) 15 | tracestate: Optional[str] = Field( 16 | default=None, 17 | description="W3C trace context tracestate header with vendor-specific trace info", 18 | ) 19 | service_tier: Optional[str] = Field( 20 | default="standard", 21 | description="Service tier for gen_ai spans (standard, premium, etc.)", 22 | ) 23 | 24 | 25 | class GenAIAttributes(BaseModel): 26 | 27 | model_provider: str = Field(default="unknown") 28 | model_name: str = Field(default="unknown") 29 | request_id: str = Field(default_factory=lambda: str(uuid.uuid4())) 30 | response_id: str = Field(default_factory=lambda: str(uuid.uuid4())) 31 | service_tier: str = Field(default="standard") 32 | token_count: Optional[int] = None 33 | 34 | def to_span_attributes(self) -> Dict[str, str]: 35 | result = {} 36 | for key, value in self.model_dump().items(): 37 | if value is not None: 38 | # Ensure all values are strings if they're not already 39 | if not isinstance(value, str) and not isinstance(value, (list, bytes)): 40 | value = str(value) 41 | result[f"gen_ai.{key}"] = value 42 | return result 43 | -------------------------------------------------------------------------------- /demo/libraries/testing/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Testing utilities and test suites for EggAI libraries. 3 | 4 | This module provides test utilities and houses unit tests for library components. 5 | """ 6 | 7 | # Re-export commonly used test utilities 8 | from .utils import ( 9 | MLflowTracker, 10 | assert_valid_agent_response, 11 | create_conversation_string, 12 | create_message_list, 13 | create_mock_agent_response, 14 | create_mock_request_message, 15 | setup_mlflow_tracking, 16 | wait_for_agent_response, 17 | ) 18 | 19 | __all__ = [ 20 | "create_message_list", 21 | "create_conversation_string", 22 | "wait_for_agent_response", 23 | "MLflowTracker", 24 | "setup_mlflow_tracking", 25 | "create_mock_agent_response", 26 | "create_mock_request_message", 27 | "assert_valid_agent_response", 28 | ] -------------------------------------------------------------------------------- /demo/libraries/testing/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test package for libraries module. 3 | """ 4 | -------------------------------------------------------------------------------- /demo/libraries/testing/utils/helpers.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Any, Dict, Optional 3 | 4 | import mlflow 5 | 6 | 7 | class MLflowTracker: 8 | 9 | def __init__( 10 | self, 11 | experiment_name: str, 12 | run_name: Optional[str] = None, 13 | params: Optional[Dict[str, Any]] = None 14 | ): 15 | self.experiment_name = experiment_name 16 | self.run_name = run_name 17 | self.params = params 18 | 19 | def __enter__(self): 20 | mlflow.set_experiment(self.experiment_name) 21 | if self.run_name is None: 22 | self.run_name = ( 23 | f"test_run_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}" 24 | ) 25 | 26 | self.run = mlflow.start_run(run_name=self.run_name) 27 | 28 | if self.params: 29 | for key, value in self.params.items(): 30 | mlflow.log_param(key, value) 31 | 32 | return self.run 33 | 34 | def __exit__(self, exc_type, exc_val, exc_tb): 35 | mlflow.end_run() 36 | return False # Don't suppress exceptions 37 | 38 | 39 | def setup_mlflow_tracking( 40 | experiment_name: str, 41 | run_name: Optional[str] = None, 42 | params: Optional[Dict[str, Any]] = None 43 | ) -> MLflowTracker: 44 | return MLflowTracker(experiment_name, run_name, params) -------------------------------------------------------------------------------- /demo/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.ruff] 2 | # Same as Black. 3 | line-length = 88 4 | # Assume Python 3.11 5 | target-version = "py311" 6 | 7 | # Exclude a variety of commonly ignored directories. 8 | exclude = [ 9 | ".bzr", 10 | ".direnv", 11 | ".eggs", 12 | ".git", 13 | ".github", 14 | ".hg", 15 | ".mypy_cache", 16 | ".nox", 17 | ".pants.d", 18 | ".pytype", 19 | ".ruff_cache", 20 | ".svn", 21 | ".tox", 22 | ".venv", 23 | "__pypackages__", 24 | "_build", 25 | "buck-out", 26 | "build", 27 | "dist", 28 | "node_modules", 29 | "venv", 30 | ] 31 | 32 | [tool.ruff.lint] 33 | # Enable flake8-bugbear (`B`) rules. 34 | select = ["E", "F", "B", "I"] 35 | 36 | # Ignore specific errors that are hard to fix in an existing codebase 37 | ignore = [ 38 | "E501", # Line too long (handled by formatter) 39 | "B904", # Within an `except` clause, raise exceptions with `raise ... from err` 40 | "F841", # Local variable is assigned to but never used 41 | "B008", # Do not perform function call in argument defaults (FastAPI pattern) 42 | "E402", # Module level import not at top of file (common in DSPy modules) 43 | ] 44 | 45 | # Allow unused variables when underscore-prefixed. 46 | dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" 47 | 48 | [tool.ruff.lint.mccabe] 49 | # Unlike Flake8, default to a complexity level of 10. 50 | max-complexity = 10 51 | 52 | [tool.ruff.lint.isort] 53 | known-third-party = ["dspy", "vespa", "mlflow", "eggai", "pytest", "opentelemetry"] -------------------------------------------------------------------------------- /demo/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = ignore::DeprecationWarning 3 | asyncio_default_fixture_loop_scope = function 4 | 5 | [pytest-asyncio] 6 | asyncio_mode = auto 7 | -------------------------------------------------------------------------------- /demo/requirements.txt: -------------------------------------------------------------------------------- 1 | eggai==0.1.46 2 | python-dotenv==1.0.1 3 | fastapi==0.115.6 4 | dspy==2.6.24 5 | psutil==7.0.0 6 | websockets==14.1 7 | guardrails-ai==0.6.2 8 | pyvespa==0.56.0 9 | tenacity==9.0.0 10 | httpx==0.28.1 11 | requests==2.32.2 12 | uvicorn==0.34.0 13 | openlit==1.33.21 14 | opentelemetry-sdk==1.33.1 15 | python-json-logger==2.0.7 16 | colorlog==6.8.2 17 | pydantic-settings==2.4.0 18 | transformers[torch]>=4.51.3 19 | peft>=0.14.0 20 | datasets>=3.3.2 21 | accelerate>=1.4.0 22 | bitsandbytes>=0.42.0 23 | trl>=0.15.2 24 | numpy==2.2.4 25 | scikit-learn==1.6.1 26 | aioboto3==13.3.0 27 | mlflow==2.21.3 28 | matplotlib==3.10.1 29 | seaborn==0.13.2 30 | pandas==2.2.3 31 | sentence-transformers==4.0.2 32 | pytest-html==4.1.1 33 | jupyter==1.1.1 34 | aiofiles>=24.1.0 35 | asyncio==3.4.3 36 | litellm==1.70.2 37 | pydantic 38 | tqdm 39 | jinja2>=3.1.3 40 | sqlalchemy>=2.0.30 41 | psycopg2-binary>=2.9.9 42 | python-multipart>=0.0.9 43 | temporalio>=1.8.0 44 | ruff==0.11.11 45 | pytest-cov==6.1.1 46 | tabulate==0.9.0 47 | docling==2.37.0 -------------------------------------------------------------------------------- /demo/sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=eggai-tech_EggAI 2 | sonar.organization=eggai-tech 3 | 4 | # Sources - specify directories with Python code 5 | sonar.sources=. 6 | 7 | # Exclude non-code files and test files from analysis 8 | sonar.exclusions=**/*.md,**/*.txt,**/*.json,**/*.yml,**/*.yaml,**/*.html,**/*.css,**/*.js,**/*.sh,**/docs/**,**/tests/**,**/*_test.py,**/test_*.py,**/shared_test_utils.py,**/__pycache__/**,**/.venv/**,**/venv/**,**/node_modules/**,**/.git/**,**/coverage/**,**/reports/**,**/dist/**,**/build/**,**/*.log 9 | 10 | # Test files (for test execution reporting) 11 | sonar.tests=. 12 | sonar.test.inclusions=**/tests/**,**/test_*.py,**/*_test.py,**/shared_test_utils.py 13 | 14 | # Coverage exclusions (exclude test files and non-code files from coverage) 15 | sonar.coverage.exclusions=**/tests/**,**/test_*.py,**/*_test.py,**/shared_test_utils.py,**/conftest.py,**/__init__.py,**/*.md,**/*.txt,**/*.json,**/*.yml,**/*.yaml,**/*.html,**/*.css,**/*.js,**/*.sh,**/docs/**,**/__pycache__/**,**/.venv/**,**/venv/**,**/setup.py 16 | 17 | # Python specific 18 | sonar.python.version=3.11 19 | 20 | # Coverage reporting 21 | sonar.python.coverage.reportPaths=coverage.xml 22 | 23 | # Test reporting 24 | sonar.python.xunit.reportPath=reports/pytest-results.xml 25 | 26 | # Language specification 27 | sonar.language=py 28 | 29 | # Source encoding 30 | sonar.sourceEncoding=UTF-8 31 | 32 | # Duplication exclusions (exclude generated or similar files) 33 | sonar.cpd.exclusions=**/tests/**,**/*_test.py,**/test_*.py,**/migrations/**,**/__init__.py,**/setup.py,**/agents/*/api_main.py,**/agents/*/main.py 34 | 35 | # Debug - log more information 36 | # sonar.verbose=true 37 | -------------------------------------------------------------------------------- /docs/docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.egg-ai.com 2 | -------------------------------------------------------------------------------- /docs/docs/assets/agent-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/agent-1.jpeg -------------------------------------------------------------------------------- /docs/docs/assets/agent-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/agent-2.jpeg -------------------------------------------------------------------------------- /docs/docs/assets/agent-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/agent-3.jpeg -------------------------------------------------------------------------------- /docs/docs/assets/agent-4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/agent-4.jpeg -------------------------------------------------------------------------------- /docs/docs/assets/agent-5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/agent-5.jpeg -------------------------------------------------------------------------------- /docs/docs/assets/agent-evaluation-dspy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/agent-evaluation-dspy.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/audit-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/audit-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/billing-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/billing-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/claims-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/claims-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/escalation-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/escalation-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/frontend-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/frontend-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/policies-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/policies-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/avatar/triage-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/avatar/triage-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/eggai-meta-framework-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/eggai-meta-framework-arch.png -------------------------------------------------------------------------------- /docs/docs/assets/example-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-00.png -------------------------------------------------------------------------------- /docs/docs/assets/example-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-01.png -------------------------------------------------------------------------------- /docs/docs/assets/example-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-02.png -------------------------------------------------------------------------------- /docs/docs/assets/example-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-03.png -------------------------------------------------------------------------------- /docs/docs/assets/example-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-04.png -------------------------------------------------------------------------------- /docs/docs/assets/example-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-05.png -------------------------------------------------------------------------------- /docs/docs/assets/example-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-06.png -------------------------------------------------------------------------------- /docs/docs/assets/example-07-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-07-chat.png -------------------------------------------------------------------------------- /docs/docs/assets/example-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-07.png -------------------------------------------------------------------------------- /docs/docs/assets/example-mcp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/example-mcp.png -------------------------------------------------------------------------------- /docs/docs/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/favicon.png -------------------------------------------------------------------------------- /docs/docs/assets/interoperability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/interoperability.png -------------------------------------------------------------------------------- /docs/docs/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/logo.png -------------------------------------------------------------------------------- /docs/docs/assets/multi-agent-human-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/multi-agent-human-chat.png -------------------------------------------------------------------------------- /docs/docs/assets/react-agent-dspy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/react-agent-dspy.png -------------------------------------------------------------------------------- /docs/docs/assets/redpanda-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/redpanda-console.png -------------------------------------------------------------------------------- /docs/docs/assets/safe-agents-guardrails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/safe-agents-guardrails.png -------------------------------------------------------------------------------- /docs/docs/assets/support-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/support-chat.png -------------------------------------------------------------------------------- /docs/docs/assets/test_tsne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/test_tsne.png -------------------------------------------------------------------------------- /docs/docs/assets/train_tsne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/train_tsne.png -------------------------------------------------------------------------------- /docs/docs/assets/triage-agent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/triage-agent.png -------------------------------------------------------------------------------- /docs/docs/assets/triage-custom-classifier-training.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/triage-custom-classifier-training.png -------------------------------------------------------------------------------- /docs/docs/assets/triage-evaluation-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggai-tech/EggAI/2855e6df6f78b17d5fb8b8053dedc2ba430ea5d2/docs/docs/assets/triage-evaluation-report.png -------------------------------------------------------------------------------- /docs/docs/concepts/agent.md: -------------------------------------------------------------------------------- 1 | # Agent 2 | 3 | An **agent** is an actor within a specific environment (e.g., software system, workflow, data pipeline, or service). Unlike static programs, agents follow clear goals, roles, or objectives. They: 4 | 5 | - **Perceive:** Gather and interpret data from their environment. 6 | - **Reason:** Use algorithms, rules, or models to choose the best action. 7 | - **Act:** Execute decisions to achieve desired outcomes and improve processes. 8 | 9 | ## Fundamental Characteristics 10 | 11 | 1. **Autonomy** 12 | Agents operate without constant human input. They use policies, models, and rules to adapt to changing conditions. 13 | 14 | 2. **Perception of the Environment** 15 | Agents integrate with data sources, APIs, and services to maintain awareness. They monitor key indicators (e.g., customer behavior, inventory, system performance) and respond in real time. 16 | 17 | 3. **Decision-Making and Reasoning** 18 | Agents apply AI methods—rules to machine learning—to evaluate actions. Their choices align with defined objectives, regulations, and business logic. 19 | 20 | 4. **Action and Influence** 21 | After deciding, agents take actions that can adjust resources, optimize operations, or make recommendations. These actions deliver tangible business value. 22 | 23 | 5. **Goal-Directed Behavior** 24 | Each agent works toward specific outcomes, such as boosting efficiency, raising customer satisfaction, cutting costs, or driving innovation. Clear goals guide their actions. 25 | 26 | 6. **(Often) Learning and Adaptation** 27 | Agents often improve over time. They learn from historical data, feedback, and performance metrics to refine their strategies and better meet evolving demands. -------------------------------------------------------------------------------- /docs/docs/concepts/multi-agent-system.md: -------------------------------------------------------------------------------- 1 | # Multi-Agent System 2 | 3 | A **multi-agent system** involves multiple agents working within the same environment. These agents interact, cooperate, or compete, collectively shaping the system’s behavior. Unlike single-agent systems, where a single entity makes all decisions and actions, multi-agent systems distribute decision-making across many autonomous agents. 4 | 5 | ## Fundamental Characteristics of Multi-Agent Systems 6 | 7 | 1. **Distributed Control** 8 | Decision-making and control are not centralized. Each agent operates autonomously, contributing to system-level goals. 9 | 10 | 2. **Interaction and Communication** 11 | Agents share information, negotiate tasks, and coordinate. This communication makes the system more responsive and adaptive. 12 | 13 | 3. **Cooperation and Competition** 14 | Agents may collaborate to achieve common objectives or compete over limited resources. Their relationships can shift as conditions evolve. 15 | 16 | 4. **Scalability and Flexibility** 17 | Multi-agent systems can grow or shrink by adding or removing agents. Their modular structure supports resilience and easier maintenance. 18 | 19 | 5. **Emergent Behavior** 20 | Complex global patterns can arise from local interactions, often resulting in innovative solutions and adaptive strategies. 21 | 22 | 6. **Heterogeneity** 23 | Agents may differ in capabilities, goals, and decision-making methods. Diversity among agents increases the system’s robustness and problem-solving potential. 24 | -------------------------------------------------------------------------------- /docs/docs/examples/agent_evaluation_dspy.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/agent_evaluation_dspy/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/coordinator.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/coordinator/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/dspy_react.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/dspy_react/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/getting_started.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/getting_started/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/langchain_tool_calling.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/langchain_tool_calling/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/litellm_agent.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/litellm_agent/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/mcp.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/mcp/README.md" %} 2 | -------------------------------------------------------------------------------- /docs/docs/examples/multi_agent_conversation.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/multi_agent_conversation/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/safe_agents_guardrails.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/safe_agents_guardrails/README.md" %} 2 | -------------------------------------------------------------------------------- /docs/docs/examples/shared_context.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/shared_context/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/triage_agent.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/triage_agent/README.md" %} -------------------------------------------------------------------------------- /docs/docs/examples/websocket_gateway.md: -------------------------------------------------------------------------------- 1 | {% include-markdown "../../../examples/websocket_gateway/README.md" %} 2 | -------------------------------------------------------------------------------- /docs/docs/index.md: -------------------------------------------------------------------------------- 1 |