SlackOps: AI Ticket Orchestrator is a Slack-first automation platform that transforms natural-language requests into structured AI-driven decisions and executes them reliably against ticketing systems. The system routes chat input through an AI reasoning layer, validates and performs ticket operations via standardized interfaces, and responds back in Slack, demonstrating production-grade orchestration, testing, observability, and infrastructure practices. This project was built following the engineering guidelines of the Open Source and Professional Software Development (OSPSD) course, with a strong emphasis on modular design, correctness, and operational readiness.
This repository contains a provider-agnostic, interface-driven system that connects a Chat interface to an AI reasoning layer and a Ticketing system. The goal is simple:
A user types a natural-language request in chat (e.g., “Create a ticket for fixing the login bug”).
The system routes the text to AI, the AI returns a structured action, the Ticketing layer executes it, and Chat replies with the result.
If you follow this README step-by-step, you should be able to set up the project locally, run the full stack, and run unit / integration / end-to-end tests.
- Quick Start (Fastest Path)
- Project Philosophy
- Quickstart Component Stack
- How the System Works
- Repository Layout
- Prerequisites
- Project Setup (Detailed)
- Configuration & Environment Variables
- Running the System Locally
- Testing
- Infrastructure & Deployment Notes
- Continuous Integration
- Development Workflow
- Troubleshooting
- Documentation Index
This is the minimum you should do to verify you can run the repository locally.
git clone https://github.com/raunak-choudhary/slackops-ai-ticket-orchestrator.git
cd slackops-ai-ticket-orchestratorThis project uses uv for dependency management.
uv sync --all-packages --devsource .venv/bin/activateCreate a .env file (recommended) or export them in your shell.
# Example (do NOT commit real keys)
export OPENAI_API_KEY="..."
export SLACK_BOT_TOKEN="..."(See Configuration & Environment Variables for the full list.)
ruff check .
mypy src tests
pytestpython main.pyIf the app starts without errors, your environment is set correctly.
This repository is built around a few non-negotiable engineering values:
Each vertical (Chat, AI, Ticketing) is defined by a standardized Abstract Base Class (ABC) contract. Implementations must strictly conform to these contracts so that provider details never leak into core logic.
The system is designed so you can swap providers (e.g., different AI providers, different ticket providers) with minimal change, ideally through configuration rather than rewrites.
Business logic never instantiates provider implementations directly. Instead, implementations are injected (via factories/configuration) so that:
- providers can be swapped,
- tests can use fakes/mocks,
- orchestration stays clean and readable.
Unit, integration, and end-to-end tests are treated as first-class features. The system is also designed so it can be deployed and monitored in a remote environment.
At runtime, the system is composed of these layers:
┌──────────────────────────┐
│ Chat Provider / Adapter │ ← receives user input, sends responses
└─────────────▲────────────┘
│
┌─────────────┴────────────┐
│ AI Provider / Adapter │ ← intent + reasoning, returns structured output
└─────────────▲────────────┘
│
┌─────────────┴────────────┐
│ Ticket Provider / Adapter │ ← executes ticket operations (CRUD/search/update)
└──────────────────────────┘
The “Integration App” (or orchestrator) wires these layers together through interfaces.
The system follows a consistent “user flow loop”:
-
User Input (Chat)
A user sends a natural-language message through a chat interface. -
Routing & Reasoning (AI)
The AI layer determines what the user wants (intent), extracts parameters, and returns a structured payload. -
Execution (Ticket Service)
The ticket layer receives a structured action (e.g.,create_ticket) and executes it against the ticket provider. -
Response (Chat)
The system formats a response and sends it back to the user through chat.
User message:
“Create a ticket for fixing the login bug and assign it to me.”
AI structured output (example shape; actual schema may vary):
{
"action": "create_ticket",
"title": "Fix login bug",
"description": "Login fails under certain session conditions",
"assignee": "me"
}Ticket layer executes:
ticket = tickets.create_ticket(
title=payload["title"],
description=payload["description"],
assignee=payload.get("assignee"),
)Chat responds:
“ Ticket created: TICKET-123 — Fix login bug”
The repository is organized by components/verticals:
.
├── src/
│ ├── chat_api/ # Chat interface contracts
│ ├── ai_api/ # AI interface contracts
│ ├── tickets_api/ # Ticket interface contracts
│ ├── *_impl/ # Provider-specific implementations (OpenAI, Gemini, Jira, etc.)
│ ├── *_adapter/ # Adaptation layers / clients
│ ├── *_service/ # Service logic (business rules)
│ └── integration_app/ # Wiring + orchestration (entrypoints, DI/config)
│
├── tests/
│ ├── unit/ # Unit tests (pure logic)
│ ├── integration/ # Integration tests (component-to-component)
│ └── e2e/ # End-to-end tests (full flow)
│
├── .circleci/ # CI pipeline definitions
├── pyproject.toml # Workspace configuration
├── README.md # This file
├── DESIGN.md # Architecture and design rationale
├── COMPONENT.md # Component documentation index
└── CONTRIBUTING.md # Contribution guidelines
Tip: If you're new to the repo, read
COMPONENT.mdfirst for a guided map of what exists and where.
You should have:
- Python (project targets Python 3.11+; your environment may use 3.12)
- uv installed and available in PATH
git- Optional but helpful:
make(if your local workflow uses Makefiles) - Credentials for providers you want to run (Slack bot token, AI keys, ticket provider tokens)
python --version
uv --version
git --versionThis is the step-by-step onboarding flow we expect all contributors to follow.
git clone https://github.com/raunak-choudhary/slackops-ai-ticket-orchestrator.git
cd slackops-ai-ticket-orchestratoruv sync --all-packages --devIf you only want to work on one package, you can still sync the full workspace to avoid resolution issues.
source .venv/bin/activateruff check .
mypy src tests
pytestIf any step fails, jump to Troubleshooting.
This project intentionally does not hardcode secrets.
All credentials must be provided via environment variables.
Create a .env file at the repository root:
# AI Provider keys
OPENAI_API_KEY="..."
GEMINI_API_KEY="..."
# Chat provider credentials
SLACK_BOT_TOKEN="..."
SLACK_SIGNING_SECRET="..."
# Ticket provider credentials
JIRA_API_TOKEN="..."
JIRA_BASE_URL="..."
JIRA_EMAIL="..."Do not commit
.env. Add it to.gitignoreif it is not already ignored.
Depending on how the app is started, you may load .env automatically (if the app uses dotenv) or manually:
set -a
source .env
set +aIf you see an error like:
Missing required environment variable: OPENAI_API_KEY
That means the app is configured to require that variable at startup.
There are two common ways to run the project locally:
- Single entrypoint (recommended): run one command that starts the integrated system.
- Component-by-component: start services independently (useful for debugging).
From the repository root:
python main.pyIf your integrated app is served via Uvicorn (example):
PYTHONPATH=src uv run uvicorn integration_app.main:app --host 0.0.0.0 --port 8000 --reloadIf you are diagnosing an issue, you may run components one-by-one.
For example, if a service is a FastAPI app, run it with Uvicorn from its package directory.
Example pattern:
cd src/<component_name>
uv run uvicorn <module_path>:app --port <port>Use this when you want to isolate a failure (e.g., AI provider vs ticket provider).
Testing is a core requirement of this repository. Tests are organized by scope.
Unit tests validate logic without depending on external services.
Run all tests:
pytestRun a specific folder:
pytest tests/unitIntegration tests validate that two components correctly interact (e.g., orchestrator + ticket service), generally using mocks or fakes for external APIs.
pytest tests/integrationE2E tests validate the full pipeline (Input → Reasoning → Execution → Output).
They may require real credentials depending on how the repository is configured.
pytest tests/e2eIf the repo uses pytest markers, use:
pytest -m "integration"
pytest -m "e2e"If you are uncertain which markers exist, run:
pytest --markersuv run pytest --cov=src --cov-report=term-missingThis project is designed to be deployable to a remote environment using Infrastructure as Code (IaC).
The deployed environment should provide:
- Environment variables for secrets
- Networking for any API endpoints
- Observability/telemetry configuration where applicable
This README focuses on local development. Deployment details belong in the IaC folder or a dedicated
DEPLOYMENT.mdif your team created one.
This repository uses CI to enforce code quality and prevent regressions.
CI typically runs:
ruff check .mypy src tests(strict typing)pytest(unit/integration/e2e depending on configuration)
CI should be treated as the “source of truth” for merge readiness.
If CI fails, fix the underlying issue rather than bypassing checks.
A clean workflow keeps the repo stable and easy to review.
Use branches like:
feature/<short-name>for featuresfix/<short-name>for bugsrefactor/<short-name>for cleanups
Use clear prefixes:
feat: ...fix: ...test: ...docs: ...refactor: ...
A good pull request should include:
- A short summary of what changed
- Why the change was needed
- How it was tested (commands + results)
If uv sync fails, ensure:
- You are at the repo root
- You are using the correct Python version
- You ran
uv sync --all-packages --dev
Try:
uv sync --all-packages --dev --reinstallRun:
ruff check . --fixIf it still fails, read the error and fix it at the reported file and line.
Mypy failures usually mean:
- Missing type annotations
- Interface mismatch
- Incorrect return types
Run:
mypy src testsFix type issues rather than disabling strict mode.
If startup fails with “Missing required environment variable”, export the variable or set it in .env and reload.
Common reasons:
- Missing real credentials
- Incorrect chat provider setup
- External provider rate limits
Start by:
- Confirming env vars are set
- Running unit/integration tests first
- Running E2E tests last
This repository includes multiple docs, each with a specific purpose:
- README.md: How to run the system and understand the big picture
- DESIGN.md: Architecture, design choices, and system rationale
- COMPONENT.md: Component index and responsibilities
- CONTRIBUTING.md: Contribution rules, PR process, and repo hygiene
If you are new:
- Read
COMPONENT.mdto understand what exists. - Read
DESIGN.mdto understand why it’s designed that way. - Use this README to run the system and tests.
- Use
CONTRIBUTING.mdbefore opening a PR.