Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
- README.md
- agent-packages/packages/assetpanda/README.md
- agent-packages/packages/common/package.json
- agent-packages/packages/github/package.json
- agent-packages/packages/github/src/schema.ts
- agent-packages/packages/jira/package.json
- agent-packages/packages/notion/package.json
- agent-packages/packages/okta/src/tools.ts
- agent-packages/packages/slack/package.json
- package.json
- src/lib/constants.ts
- src/llm/agent-evals/jira-agent/test-data.ts
- src/slack/views/app_home.ts
Quix is an AI-powered Slack agent designed to interact with various business tools like JIRA, GitHub, and HubSpot directly from Slack. It uses natural language processing to understand user requests and execute actions on their behalf. The system is built with a modular architecture, leveraging Nest.js for the core application and a monorepo structure for scalable integration management.
The architecture prioritizes extensibility, allowing new integrations to be added as self-contained packages. This design ensures that the core application remains decoupled from the specific logic of each external service, facilitating easier maintenance and development.
Sources: README.md:3-5, README.md:19-20
Core Components
The Quix system is composed of a main Nest.js application and a collection of "agent packages". The main application handles Slack communication, LLM orchestration, and state management, while the agent packages provide the specific tools for interacting with external services.
This diagram illustrates the high-level project structure.
Sources: README.md:22-36
Main Application (src/)
The core of Quix is a Nest.js application responsible for:
- Slack Integration: Handling events, interactions, and messages from the Slack API.
- LLM Orchestration: Processing user queries using an LLM (e.g., OpenAI) to determine intent and select appropriate tools.
- State Management: Managing workspace configurations, user authentications, and connection details using a PostgreSQL database and Redis for caching.
- API Endpoints: Providing necessary endpoints for Slack OAuth, event subscriptions, and health checks.
Sources: README.md:22-28, README.md:52-61
Agent Packages (agent-packages/)
Integrations with external services are encapsulated within individual packages in the agent-packages/packages/ directory. This modular approach allows for clean separation of concerns and independent development of each integration.
Each agent package typically includes:
- Tool Definitions: Functions that the LLM can call to perform actions (e.g.,
get_jira_issue,create_github_pr). These are built using@clearfeed-ai/quix-common-agent. - Service Logic: The implementation for communicating with the external service's API.
- Type Definitions: TypeScript interfaces for the external service's data models.
- Input Schemas: Zod schemas for validating the arguments passed to tools.
The diagram below shows the relationship between the main application and the agent packages.
User Interaction Flow
The following sequence diagram illustrates a typical user interaction, from sending a message in Slack to receiving a response from Quix.
This flow demonstrates how a user's natural language query is translated into a series of tool calls to fulfill the request. The test data for the Jira agent provides concrete examples of this process.
Sources: src/llm/agent-evals/jira-agent/test-data.ts:5-22, README.md:73-75
Supported Integrations
Quix supports a variety of business tools. Integrations can be configured via the App Home in Slack. Some integrations use OAuth for authentication, while others require API tokens or other credentials.
| Integration | Description | OAuth |
|---|---|---|
| JIRA | Create, search, and update issues in JIRA | true |
| GitHub | Create, update, and search issues or PRs in GitHub | true |
| Hubspot | Track contacts, companies, and deals in HubSpot | true |
| Zendesk | Create, update, and view tickets in Zendesk | false |
| Postgres | Run natural-language queries on your Postgres database | false |
| Salesforce | View and update opportunities, contacts, and accounts in Salesforce | true |
| Notion | Search, browse, and retrieve content from your Notion workspace | false |
| Linear | Manage and search tasks or issues in Linear | false |
| Okta | Look up users, groups, and apps in Okta | false |
| JumpCloud | Look up users, and groups in JumpCloud | false |
Sources: src/lib/constants.ts:20-176
Agent Package Details
Each agent package is a standalone project responsible for a single integration. This modularity is enforced by a common structure and a set of dependencies.
Common Structure
A typical agent package, such as the AssetPanda agent, has the following structure:
src/
├── index.ts # Main service implementation
├── tools.ts # Tool definitions for the agent
├── types.ts # TypeScript interfaces
├── schema.ts # Zod schemas for validation
└── ... # Tests and other files
Sources: agent-packages/packages/assetpanda/README.md:104-111
Tool Definition
Tools are the core of an agent package. They are defined with a name, description, input schema, and the function to execute. The description is critical, as it's used by the LLM to decide which tool to use for a given query.
The example below from the Okta agent shows how the list_okta_users tool is defined.
// From agent-packages/packages/okta/src/tools.ts
tool({
name: 'list_okta_users',
description:
'List users in Okta using the search or filter parameter...',
schema: SCHEMAS.listUsers,
operations: [ToolOperation.READ],
func: async (args: z.infer<typeof SCHEMAS.listUsers>) => service.listUsers(args)
})
Sources: agent-packages/packages/okta/src/tools.ts:252-260
Input Validation
Agent packages use Zod to define schemas for tool inputs. This ensures that the data passed from the LLM to the tool function is correctly structured and typed. For integrations with default configurations (like a default GitHub repo), a conditional schema can be created.
// From agent-packages/packages/github/src/schema.ts
export const getGithubIssueSchema = (config: GitHubConfig) =>
z.object({
repo: createConditionalDefaultSchema(
config.repo,
'Repository name from which the issue or PR should be retrieved'
),
owner: createConditionalDefaultSchema(
config.owner,
'Owner of the repository containing the issue or PR'
),
issueNumber: z
.number()
.describe(
'The number of the issue or PR to fetch. PRs and Issues are interchangeable terms in GitHub'
)
});
Sources: agent-packages/packages/github/src/schema.ts:68-85
Technology Stack
The project is built on a modern TypeScript stack, utilizing several key libraries and frameworks.
| Category | Technology | Usage |
|---|---|---|
| Backend Framework | Nest.js | Core application structure, dependency injection. |
| AI/LLM | LangChain.js, OpenAI/Google GenAI | LLM orchestration, agent creation, tool management. |
| Database | Sequelize, PostgreSQL | ORM and relational database for persistent storage. |
| Caching | Redis | Caching workspace configurations and other data. |
| Slack Integration | @slack/web-api, slack-block-builder | Communicating with Slack API and building UI components. |
| Validation | Zod | Data validation for tool inputs and API payloads. |
| Monorepo Mgmt | Yarn Workspaces, Shell Scripts | Managing dependencies and builds for agent packages. |
Sources: package.json:24-61, README.md:42-50