Skip to content
swatv3nubPublic

About

a modular AI agent built for real-world decision-making, context handling, and workflow automation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

ActiQ — CommuteAI Agent

ActiQ is a production-oriented workplace assistant that helps employees plan their workday around commutes, desk bookings, meetings, team presence and organizational knowledge. It combines deterministic services and databases for all factual state with an LLM that only phrases answers from verified tool results — the LLM can never fabricate availability, bookings, meeting times or traffic data.


Architecture

Web / Client ──► FastAPI (REST, auth-ready) ──► ActiQ Agent orchestrator
                                                   │
        ┌──────────────────┬────────────────────┬──┴───────────┐
        ▼                  ▼                    ▼              ▼
  CommutePlannerTool  DeskAvailabilityTool  MeetingLookupTool  TeamStatusTool / KnowledgeSearchTool
        │                  │                    │              │
        ▼                  ▼                    ▼              ▼
  Maps provider      PostgreSQL/SQLite     Calendar provider   RAG retriever
  (mock or Google)   (SQLAlchemy)          (DB-seeded mock)    (local vector store)
  • Provider independence — Gemini and Groq are both supported behind a common LLMProvider interface (actiq/providers/). Selection is purely configuration-driven; business logic contains no vendor branches.
  • Deterministic core — intent classification, tool routing, booking validation and answer composition have deterministic implementations. The LLM receives tool facts as JSON data and only writes prose; if no LLM is configured or it fails, a template composer renders the same facts.
  • Grounding & verification — every response carries structural source metadata (VERIFIED / PARTIALLY_VERIFIED / INFERRED / UNKNOWN), confidence, assumptions and the tools used. No chain-of-thought is exposed.

Project layout

actiq/
├── main.py               # FastAPI app factory + lifespan wiring
├── api_service.py        # backwards-compatible app re-export
├── config.py             # pydantic-settings configuration (fail-fast)
├── app_context.py        # dependency wiring for services/agent/RAG
├── observability.py      # structured JSON logging
├── api/                  # routes, schemas, middleware, auth dependency
├── agent/                # intents, tools, state, prompts, compose, graph, sessions
├── services/             # employees, desks, meetings, commute (deterministic)
├── rag/                  # ingest, embeddings, vector store, retriever, injection guard
├── db/                   # SQLAlchemy models, repository, seeder
└── providers/            # llm interface, gemini, groq, maps, calendar
data/                     # mock datasets + knowledge documents
tests/                    # unit, integration and evaluation suites
scripts/                  # ingest.py, seed_db.py, run_evaluation.py
docs/EVALUATION.md        # recorded evaluation metrics

Setup

Requirements: Python 3.10+ (developed on 3.14).

python -m venv .venv
.venv\Scripts\Activate.ps1        # Windows (bash: source .venv/bin/activate)
pip install -r requirements.txt
Copy-Item .env.example .env       # bash: cp .env.example .env

Environment variables

Variable Default Purpose
LLM_PROVIDER gemini Active LLM provider: gemini | groq
GEMINI_API_KEY — Required iff provider is gemini
GEMINI_MODEL gemini-2.5-flash Gemini model id
GROQ_API_KEY — Required iff provider is groq
GROQ_MODEL llama-3.3-70b-versatile Groq model id
LLM_FALLBACK_ENABLED false Opt-in cross-provider fallback
LLM_FALLBACK_PROVIDER — Provider used when fallback enabled
LLM_TEMPERATURE / LLM_MAX_OUTPUT_TOKENS / LLM_TIMEOUT_SECONDS / LLM_MAX_RETRIES see .env.example Generation controls
GOOGLE_MAPS_API_KEY — Optional; enables live routing (otherwise deterministic mock dataset)
DATABASE_URL sqlite:///./actiq.db SQLAlchemy URL (PostgreSQL works unchanged)
VECTOR_STORE_PATH ./data/vectorstore Persisted RAG index location
RAG_TOP_K 4 Chunks fetched per knowledge search
LOG_LEVEL INFO Root log level
API_KEY — Optional; when set, requires X-API-Key header on API routes
MAX_REQUEST_BYTES 65536 Rejects larger request bodies (413)
SESSION_TTL_MINUTES 120 In-memory session retention
BOOKINGS_ENABLED true Master switch for desk write operations

Only the selected provider's key is required. Startup fails fast with a clear error if the active provider has no key.

Selecting Gemini

LLM_PROVIDER=gemini
GEMINI_API_KEY=your-key
GEMINI_MODEL=gemini-2.5-flash

Selecting Groq

LLM_PROVIDER=groq
GROQ_API_KEY=your-key
GROQ_MODEL=llama-3.3-70b-versatile

Switching providers needs no code changes — flip LLM_PROVIDER and supply that provider's key/model. Pick a currently supported model id from your provider's console (model names evolve; the defaults above were current at implementation time). Without any usable key the service still runs in deterministic mode (template-composed answers), which is how tests operate.


Mock data

All datasets are clearly fictional and live in data/:

  • employee_directory.json — employees, teams, offices, scheduled in-office days
  • desks.json — desks, floors, zones, features, near-team hints
  • desk_bookings.csv — static bookings (a demo booking is materialized daily)
  • commute_routes.json — home→office route durations (typical vs peak)
  • meetings.json — weekday-keyed meeting templates materialized per day
  • knowledge/*.md — office policies indexed by RAG

The database seeds automatically at startup and refreshes date-sensitive rows (meetings/bookings) once per day. Attendance follows one explicit rule: an employee is "in office" iff today's weekday appears in their attendance_days. Calendars are never used to infer presence.

RAG ingestion

Ingestion chunks data/knowledge/*.md, indexes structured dataset summaries, embeds them with a deterministic local embedding model and persists the index:

python scripts/ingest.py

The API also auto-ingests on startup if the index is missing. Re-running is safe (idempotent rebuild).

Running tests

python -m pytest

95+ tests cover services, tools, intent routing, RAG (including prompt-injection guard), provider adapters (mocked SDKs), the API, and the evaluation suite. No live credentials are required — external APIs are mocked.

Evaluation suite only (writes docs/EVALUATION.md):

python scripts/run_evaluation.py

Running the API

uvicorn actiq.main:app --reload
# legacy alias also works: uvicorn actiq.api_service:app --reload

Interactive OpenAPI docs: http://localhost:8000/docs

Example requests

curl http://localhost:8000/health

curl -X POST http://localhost:8000/ask \
  -H "Content-Type: application/json" \
  -d '{"user_id": "emp_001", "query": "When should I leave to reach the office by 9 AM?"}'

Example /ask response shape:

{
  "answer": "Leave around 08:10 to reach Prestige Tech Park by 09:00 ...",
  "intent": "COMMUTE",
  "sources": [
    {"name": "Commute Routes Dataset", "type": "mock_database",
     "verification": "VERIFIED"}
  ],
  "assumptions": ["Departure time is derived from the route duration estimate..."],
  "confidence": 0.85,
  "verification": "PARTIALLY_VERIFIED",
  "tool_calls": ["CommutePlannerTool"],
  "request_id": "..."
}

Booking endpoints:

curl -X POST http://localhost:8000/bookings -H "Content-Type: application/json" \
  -d '{"employee_id": "emp_002", "desk_id": "D-102", "date": "2026-08-25"}'
curl http://localhost:8000/bookings/emp_002
curl -X DELETE "http://localhost:8000/bookings/<booking_id>?user_id=emp_002"
curl http://localhost:8000/meetings/emp_001

Conflicts return HTTP 409; unauthorized cancellations return 403; invalid input returns 422.

Docker usage

docker build -t actiq .
docker run --rm -p 8000:8000 \
  -e LLM_PROVIDER=groq -e GROQ_API_KEY=$GROQ_API_KEY \
  actiq

The image runs as a non-root user, carries no secrets, and includes a health check hitting /health. A docker-compose.yml is intentionally omitted: the default deployment uses SQLite and the local vector store, so there are no extra services to orchestrate yet.

Known limitations

  • Live Gemini/Groq and Google Maps integrations are implemented against their SDKs but verified only through mocks in this environment (no real credentials available here); run a quick smoke test after adding keys.
  • The vector store is an in-process cosine-similarity index — fine for policy corpora, swap in pgvector/FAISS for large scale.
  • Sessions are in-memory (single process); use Redis for multi-worker deploys.
  • Attendance reflects scheduled directory days only; no check-in feeds.
  • The evaluation suite measures the offline pipeline (MockLLMProvider); phrasing quality with a live LLM is not automatically scored.

Future improvements

Real Google Calendar OAuth · live traffic alerts · PostgreSQL + pgvector · Redis-backed sessions · Prometheus/OpenTelemetry · web dashboard · calendar-aware desk recommendations.

See docs/API_Documentation.md for endpoint details and docs/EVALUATION.md for recorded metrics.

License

Released under the MIT License.

About

a modular AI agent built for real-world decision-making, context handling, and workflow automation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages