A collection of cognitive agents for processing OpenTelemetry data and evidence gathering for reasoning systems.
- Ingestion Service β Extracts knowledge from OpenTelemetry traces (entities, relations, embeddings).
- Evidence Gathering Service β Retrieves relevant evidence from the knowledge graph (e.g. βWhat does Miss-Marple do?β).
- Semantic Negotiation Agent β Handles multi-party semantic negotiation using NegMAS and SSTP (Semantic State Transfer Protocol).
The evidence service can use an optional mocked DB (Neo4j-backed graph API). For that setup, run the mocked-db service and set DATA_LAYER_BASE_URL or MOCKED_DB_BASE_URL; see evidence/README.md. When running via the unified gateway (Docker or local), the in-memory cache is used and no external data layer is required.
The gateway serves both ingestion and evidence on port 9004. It uses a .env file at repo root (see Environment setup); create it from .env.example if needed.
# From repo root (ensure .env exists with Azure OpenAI credentials, etc.)
docker compose up --buildThen use the API at http://localhost:9004:
| Backend | Path | Example |
|---|---|---|
| Gateway health | /health |
GET http://localhost:9004/health |
| Ingestion | /api/knowledge-mgmt/extraction |
POST http://localhost:9004/api/knowledge-mgmt/extraction |
| Evidence | /api/knowledge-mgmt/reasoning/evidence |
POST http://localhost:9004/api/knowledge-mgmt/reasoning/evidence |
Confluence paths (above); prefixed paths also work: /ingestion/..., /evidence/.... Cache is in-process only (not exposed); ingestion and evidence share it inside the container.
Requirement: a .env file with at least Azure OpenAI credentials (see Environment setup below). Create it from the template:
cp .env.example .env
# Edit .env and set AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_API_KEY, etc.One-time setup so the gateway can import ingestion, evidence, and caching:
./scripts/setup_local_links.shThen (from repo root):
PYTHONPATH=. poetry run uvicorn gateway.app.main:app --host 0.0.0.0 --port 9004Use http://localhost:9004 as the base URL (see API paths in the Quick Start section above).
For development/testing, you can run agents as standalone services:
Click to expand: Individual agent commands
Ingestion Agent (standalone, port 8080):
cd ingestion
poetry run uvicorn app.main:app --host 0.0.0.0 --port 8080Evidence Agent (standalone, port 8087):
cd evidence
poetry run uvicorn app.main:app --host 0.0.0.0 --port 8087Semantic Negotiation Agent (independent service, port 8089):
cd semantic_negotiation
poetry run uvicorn app.main:app --host 0.0.0.0 --port 8089
# Test with two-agent simulation
poetry run python semantic_negotiation/test_two_agents.py
# Or with custom acceptance thresholds
poetry run python semantic_negotiation/test_two_agents.py --threshold-a 0.4 --threshold-b 0.3Note: The gateway (port 9004) is the recommended production setup. It runs ingestion + evidence in a single process with shared in-memory cache. The semantic negotiation agent is a separate service that runs independently.
The CI pipeline automatically builds and publishes a unified Docker image using GitHub Actions.
When you open a PR:
git checkout -b feature/my-changes
git push origin feature/my-changes
# Open PR on GitHubWhat happens:
- β Runs unit tests
- β Builds unified Docker image (validation only)
- β Does NOT push image to registry
- π― Purpose: Catch Docker build regressions early
When you merge to main:
git checkout main
git pull origin main
git merge feature/my-changes
git push origin mainWhat happens:
- β Runs unit tests
- β Builds unified Docker image
- β
Pushes with
latesttag to GHCR
Published image:
ghcr.io/<org>/ioc-cfn-cognitive-agents:latest
To create a production release:
# Create and push a semantic version tag
git tag v1.0.0
git push origin v1.0.0What happens:
- β
Validates tag follows semantic versioning (
vX.Y.Z) - β Runs unit tests
- β Builds unified Docker image
- β Pushes with version tag to GHCR
Published image:
ghcr.io/<org>/ioc-cfn-cognitive-agents:v1.0.0
Valid tag formats:
v1.0.0- Standard releasev2.3.4-alpha.1- Pre-releasev1.0.0-beta- Beta releasev3.2.1-rc.2- Release candidate
Invalid tags will fail CI:
1.0.0(missingvprefix)v1.2(incomplete version)release-1(not semver)
The recommended way to run is the unified gateway image (single process, port 9004):
# Pull and run the unified gateway (ingestion + evidence on port 9004)
docker pull ghcr.io/<org>/ioc-cfn-cognitive-agents:latest
docker run -p 9004:9004 ghcr.io/<org>/ioc-cfn-cognitive-agents:latestThen use http://localhost:9004 for ingestion and evidence paths (see Quick Start).
All images are built for:
linux/amd64(x86_64)linux/arm64(Apple Silicon, ARM servers)
- Ensure tests pass:
poetry run pytest - Update version in code (if needed)
- Create semantic version tag:
git tag v1.0.0 - Push tag:
git push origin v1.0.0 - Monitor CI: Check GitHub Actions for build status
- Verify image:
docker pull ghcr.io/<org>/ioc-cfn-cognitive-agents:v1.0.0
The cognition-engine package auto-publishes to Artifactory on push to clawbee branch.
git checkout clawbee
git push origin clawbeeCI automatically:
- Generates dev version:
0.1.0.dev1,0.1.0.dev2, etc. (PEP 440) - Builds
.tar.gzand.whlpackages - Publishes to Artifactory using Vault credentials
# Update version in pyproject.toml
poetry version minor # 0.1.0 β 0.2.0 (or: patch, major)
# Commit and push
git add pyproject.toml
git commit -m "chore: bump version to 0.2.0"
git push origin clawbeeNext publish will be 0.2.0.dev1, then 0.2.0.dev2, etc.
pip install cognition-engine --extra-index-url https://<artifactory-url>/artifactory/api/pypi/outshift-pypi/simplePackage includes: ingestion, evidence, caching, gateway modules
Usage examples: docs/usage.md
- Python 3.11+
- Poetry
- Docker (for containerized development)
A .env file is required for the gateway (local and Docker) so ingestion and evidence have credentials and options.
Location: Place .env at repo root (ioc-cfn-cognitive-agents/.env). This single file is used by:
- Local development (gateway, ingestion, evidence)
- Docker Compose (via
env_filein compose.yaml) - CI/CD workflows
Create from template:
# From repo root
cp .env.example .env
# Edit .env and set your values (see below)Required and optional variables:
| Variable | Required | Description |
|---|---|---|
AZURE_OPENAI_ENDPOINT |
Yes (for ingestion) | Azure OpenAI endpoint URL. Ingestion needs this for LLM-based extraction. |
AZURE_OPENAI_API_KEY |
Yes (for ingestion) | Azure OpenAI API key. |
AZURE_OPENAI_DEPLOYMENT |
No | Deployment name (default: gpt-4o). |
AZURE_OPENAI_API_VERSION |
No | API version (default: 2024-08-01-preview). |
EMBEDDING_MODEL_PATH |
No | Path to local bge-small-en-v1.5 folder. If set, ingestion and evidence use it instead of downloading from Hugging Face. Use bge-small-en-v1.5 (relative to repo root) or an absolute path. |
ENABLE_EMBEDDINGS |
No | Enable embedding generation (default: true). |
ENABLE_DEDUP |
No | Enable semantic deduplication (default: true). |
SIMILARITY_THRESHOLD |
No | Dedup threshold 0.0β1.0 (default: 0.95). |
MOCKED_DB_BASE_URL |
No | Evidence: external mocked DB URL (optional). |
MGMT_PLANE_URL, COGNITION_ENGINE_* |
No | Management plane / engine registration. |
The same .env can contain variables for multiple services; each app ignores unknown keys. See .env.example for a full template.
# Run all tests
poetry run pytest
# Run with coverage
poetry run pytest --cov=app --cov-report=html
# Run specific service tests
cd ingestion && poetry run pytest
cd evidence && poetry run pytest
cd caching && poetry run pytest# Linting
poetry run ruff check .
# Auto-fix
poetry run ruff check --fix .
# Format
poetry run ruff format .The unified gateway runs ingestion and evidence in one process with a shared in-memory cache (port 9004):
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OpenTelemetry Traces β
βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββ
β Unified Gateway (port 9004) β
β βββββββββββββββββββββββ ββββββββββββββββββββ β
β β Ingestion β β Evidence β β
β β - Extract entities β β - Query intent β β
β β - Generate embeddingsβ β - Path finding β β
β β - Build relations β β - Evidence rank β β
β ββββββββββββ¬ββββββββββββ ββββββββββ¬ββββββββββ β
β β In-memory cache β β
β βββββββββββββββββ¬βββββββββ β
βββββββββββββββββββββββββββββββΌββββββββββββββββββββ
β
(optional) βΌ
βββββββββββββββββββββββββββββββββ
β External graph (e.g. Neo4j) β
β when DATA_LAYER_BASE_URL set β
βββββββββββββββββββββββββββββββββ
Problem: First startup hangs or fails with SSL certificate errors when downloading the bge-small-en-v1.5 model from HuggingFace.
Solution 1: Let fastembed download automatically (Recommended)
Remove any corrupted local model directory and let fastembed download fresh:
# Remove corrupted Git LFS pointer files if they exist
rm -rf bge-small-en-v1.5/
# For corporate SSL certificate issues, add to .env:
HTTPX_VERIFY=false
OPENAI_VERIFY_SSL=falseThe model (~127MB) downloads to /tmp/fastembed_cache on first run. Subsequent runs use the cached version.
Solution 2: Manual download from cache
If fastembed already downloaded the model to /tmp/fastembed_cache, copy it to the repo:
# Find the cached model
ls /tmp/fastembed_cache/models--qdrant--bge-small-en-v1.5-onnx-q/snapshots/*/
# Copy to repo root
mkdir -p bge-small-en-v1.5
cp -L /tmp/fastembed_cache/models--qdrant--bge-small-en-v1.5-onnx-q/snapshots/*/model_optimized.onnx bge-small-en-v1.5/
cp -L /tmp/fastembed_cache/models--qdrant--bge-small-en-v1.5-onnx-q/snapshots/*/*.json bge-small-en-v1.5/
cp -L /tmp/fastembed_cache/models--qdrant--bge-small-en-v1.5-onnx-q/snapshots/*/vocab.txt bge-small-en-v1.5/Now local dev and Docker builds will use the bundled model (no download needed).
Solution 3: Git LFS (not recommended)
If the model files are in a Git LFS repository, you need Git LFS installed:
brew install git-lfs # macOS
git lfs install
git lfs pullHowever, Solution 1 (fastembed auto-download) is cleaner and doesn't bloat your repository.
The Dockerfile includes SSL bypass for model downloads. If you still encounter issues:
# In Dockerfile, ensure these lines exist (already present):
RUN export HF_HUB_DISABLE_SSL_VERIFY=1 && \
export CURL_CA_BUNDLE="" && \
/opt/venv/bin/python -c "from fastembed import TextEmbedding; ..."Problem: [SSL: CERTIFICATE_VERIFY_FAILED] when calling Azure OpenAI API.
Solution: The code automatically disables SSL verification when HTTPX_VERIFY=false is set in .env:
# Add to .env
HTTPX_VERIFY=falseThe ingestion and evidence services read this variable and configure httpx.Client(verify=False) for the Azure OpenAI client.
Problem: After the monorepo refactoring, old test commands reference outdated directory names.
Solution: Use the correct directory names:
# Old (incorrect):
cd ingestion-cognitive-agent && poetry run pytest
# New (correct):
cd ingestion && poetry run pytest
cd evidence && poetry run pytestOr run all tests from the root:
poetry run pytestThis monorepo uses Poetry with package-mode = true and is ready for publishing to JFrog or PyPI:
ioc-cfn-cognitive-agents/
βββ pyproject.toml # Single package definition
βββ gateway/ # Unified FastAPI app
β βββ __init__.py
β βββ app/
βββ ingestion/ # Knowledge extraction service
β βββ __init__.py
β βββ app/
βββ evidence/ # Evidence gathering service
β βββ __init__.py
β βββ app/
βββ caching/ # Shared caching layer
β βββ __init__.py
β βββ app/
βββ semantic_negotiation/ # Separate negotiation service
Benefits:
- β
Single
pip install ioc-cfn-cognitive-agentsgets everything - β
Shared dependencies in one
pyproject.toml - β
Directory names match Python imports (
from ingestion.app...) - β No symlink workarounds needed
- β
Ready for
poetry buildandpoetry publish
- Create a feature branch:
git checkout -b feature/my-feature - Make changes and add tests
- Ensure tests pass:
poetry run pytest - Push and open a PR (CI will validate build)
- After merge,
latestimages are auto-published - Tag releases with semantic versions for production
[Add your license here]