Conversation State Management
Relevant source files
The following files were used as context for generating this wiki page:Conversation State Management is a core feature of Quix that enables the AI agent to maintain context across multiple interactions within a single Slack thread. It achieves this by persisting key information about the conversation, such as previous tool calls and the agent's execution plan, into a database. This allows the agent to handle complex, multi-step queries that require memory of past actions and results.
The system is designed to track each conversation (defined by a Slack channel and thread timestamp) and associate it with a specific Slack workspace. This state is crucial for providing coherent and context-aware responses, remembering previous tool outputs, and following a generated plan to fulfill a user's request. The state is managed primarily by the LlmService, which reads and writes to the ConversationState model before and after processing a user's message.
Database Schema
The state of each conversation is stored in the conversation_states table. Each record represents a unique conversation thread within a Slack workspace.
Sources: src/database/models/conversation-state.model.ts, src/database/models/slack-workspace.model.ts
Entity Relationship Diagram
The following diagram illustrates the relationship between a SlackWorkspace and its associated ConversationState records. A single workspace can have many conversation states.
conversation_states Table Schema
The table stores all the necessary context for a conversation thread.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | UUID | Primary Key, Not Null, Default: gen_random_uuid() | Unique identifier for the conversation state record. |
team_id | VARCHAR | Not Null, Foreign Key to slack_workspaces | The ID of the Slack workspace (team_id). |
channel_id | VARCHAR | Not Null | The ID of the Slack channel where the conversation is taking place. |
thread_ts | VARCHAR | Not Null | The timestamp of the parent message in the thread, acting as the thread identifier. |
last_tool_calls | JSONB | Nullable | Stores the results of tools executed previously in the conversation. The key is a tool call ID, and the value contains the name, args, and result. |
last_plan | JSONB | Nullable | Stores the multi-step plan generated by the agent to address the user's query. Includes the steps and a completion flag. |
contextual_memory | JSONB | Not Null, Default: {} | A flexible field for storing any other contextual information. |
message_count | INTEGER | Not Null, Default: 0 | A counter for the number of messages processed in this conversation thread. Used for trial limitations. |
created_at | DATE | Not Null | Timestamp of when the conversation state was first created. |
updated_at | DATE | Not Null | Timestamp of the last update to the conversation state. |
Sources: src/database/models/conversation-state.model.ts:13-64
State Management Flow
The LlmService is the central component responsible for orchestrating conversation state. For every message processed, it retrieves, uses, and updates the state.
Sources: src/llm/llm.service.ts, src/slack/slack-events-handler.service.ts
Message Processing Sequence
This diagram shows the sequence of operations when a user message is processed.
Key Operations in LlmService
-
State Retrieval/Creation: Upon receiving a message,
LlmServiceperforms anupserton theconversation_statestable using theteam_id,channel_id, andthread_ts. This ensures a state record exists for the conversation.
Sources: src/llm/llm.service.ts:82-92 -
Context Enhancement: The
enhanceMessagesWithToolContextmethod augments the message history sent to the LLM. It adds system messages containing:- The URL of the Slack thread, instructing the agent to include it in any created resources (e.g., Jira tickets).
- A summary of previous tool calls and their results from
conversationState.last_tool_calls. This gives the agent memory of its past actions.
Sources: src/llm/llm.service.ts:37-65, src/llm/types.ts:25-31
-
State Update: After the
QuixAgentprocesses the message and executes tools, theLlmServiceupdates theconversationStaterecord:last_planis populated with the plan generated by the agent.last_tool_callsis updated with the results of any newly executed tools.message_countis incremented.- The updated record is saved back to the database.
Sources: src/llm/llm.service.ts:164-183
State Data Structures
The last_tool_calls and last_plan JSONB fields have specific structures that are critical for the agent's operation.
Sources: src/database/models/conversation-state.model.ts, src/llm/quix-agent.ts, src/llm/types.ts
last_tool_calls
This object acts as a memory of tool executions within the thread.
{
"tool_call_id_1": {
"name": "tool_name",
"args": { "arg1": "value1" },
"result": "tool output"
},
"tool_call_id_2": {
"name": "another_tool",
"args": { "argX": "valueY" },
"result": "output from another tool"
}
}
Sources: src/database/models/conversation-state.model.ts:43-50, src/llm/llm.service.ts:56-61
last_plan
This object stores the sequence of steps the agent intends to take. The QuixAgent generates this plan before execution.
{
"steps": [
{
"type": "tool",
"tool": "toolName",
"args": { "param": "value" }
},
{
"type": "reason",
"input": "Synthesize the results and answer the user."
}
],
"completed": false
}
Sources: src/database/models/conversation-state.model.ts:52-58, src/llm/quix-agent.ts:166-170, src/llm/types.ts:46-51
Conversation Lifecycle and Constraints
The conversation state is subject to lifecycle rules to manage resources and enforce usage limits.
Conversation Expiration
To prevent context from becoming stale and overly long, conversations have a soft retention period.
- A constant
SOFT_RETENTION_DAYS(set to 7) defines this period. - In
LlmService, if a message is received in a thread where theconversationStatewas created more than 7 days ago, the agent will not process the request and will instead instruct the user to start a new thread.
Sources: src/llm/llm.service.ts:93-102, src/lib/constants.ts:208
Trial Mode Limitations
For workspaces in trial mode (i.e., without a custom OpenAI key set), there is a limit on the number of messages per conversation.
- The
TRIAL_MAX_MESSAGE_PER_CONVERSATION_COUNTconstant defines this limit. - If
slackWorkspace.isTrialModeis true and theconversationState.message_countreaches this limit, the agent will stop responding and prompt the user to add their OpenAI key to remove the restriction.
Sources: src/llm/llm.service.ts:104-111, src/database/models/slack-workspace.model.ts:133-140
Summary
Conversation State Management is a foundational system in Quix that transforms the agent from a simple command-responder into a context-aware assistant. By persisting conversation history, tool calls, and execution plans in the conversation_states table, the LlmService and QuixAgent can handle complex, multi-turn interactions. This stateful architecture is key to the agent's ability to understand context, follow through on plans, and provide intelligent, coherent responses within a continuous Slack conversation.