# SupportAgentService

**Kind:** Service

**Source:** [`atloria-monorepo/apps/api/src/support-agent/support-agent.service.ts`](https://github.com/sherkety/atloria/blob/main/atloria-monorepo/apps/api/src/support-agent/support-agent.service.ts#L24)

`SupportAgentService` manages support-agent configuration and agent lifecycle operations, including creating, updating, listing, and deleting support agents. It also provides chat and streaming-chat capabilities while preserving access to conversation history. In the NestJS API, controllers or other backend services use it as the primary integration point for support-agent administration and messaging.

## Methods

| Method | Signature | Returns | Description |
|---|---|---|---|
| `getConfig` | `getConfig(projectId: string)` | `unknown` |  |
| `upsertConfig` | `upsertConfig(projectId: string, organizationId: string, dto: UpsertSupportAgentConfigDto)` | `unknown` |  |
| `listAgents` | `listAgents(projectId: string)` | `unknown` |  |
| `createAgent` | `createAgent(projectId: string, organizationId: string, dto: any)` | `unknown` |  |
| `getAgent` | `getAgent(agentId: string)` | `unknown` |  |
| `updateAgent` | `updateAgent(agentId: string, dto: any)` | `unknown` |  |
| `deleteAgent` | `deleteAgent(agentId: string)` | `unknown` |  |
| `chat` | `chat(projectId: string, agentId: string, organizationId: string, message: string, opts: {
      versionNumber?: number;
      conversationHistory?: Array<{ role: string; content: string }>;
      sessionId?: string;
    })` | `unknown` |  |
| `chatStream` | `chatStream(projectId: string, agentId: string, organizationId: string, message: string, opts: {
      versionNumber?: number;
      conversationHistory?: Array<{ role: string; content: string }>;
      sessionId?: string;
    })` | `unknown` | Stream chat response (SSE) Yields chunks as they come from the AI, then saves to history |
| `getChatHistory` | `getChatHistory(projectId: string, agentId: string, limit: unknown)` | `unknown` | Get chat history for an agent Returns all messages from active sessions |
| `clearChatHistory` | `clearChatHistory(projectId: string, agentId: string)` | `unknown` | Clear chat history for an agent (end current session) |
| `search` | `search(projectId: string, organizationId: string, query: string, limit: unknown, docVersionId: string)` | `unknown` | Scoped RAG search for support agent. |
| `searchAll` | `searchAll(projectId: string, organizationId: string, query: string, limit: unknown)` | `unknown` | Search all document types for a project — used by the public search bar. |

## Dependencies

- `PrismaService`
- `AzureSearchService`
- `LanguageDetectorService`
- `AgentAdapterService`

## Where it refuses work

- `SupportAgentService` stops the work with `NotFoundException` when `!agent.isEnabled` — “Agent not found or disabled”, in 2 places.
- `SupportAgentService` stops the work with `NotFoundException` when `!project` — “Project not found”, in 2 places.
- `SupportAgentService` stops the work with `NotFoundException` when `existingCount >= MAX_AGENTS_PRO`.
- `SupportAgentService` stops the work with `NotFoundException` when `!agent` — “Agent not found”.
- `SupportAgentService` stops the work with an early return when `seen.has(r.id)`, in 2 places.
- `SupportAgentService` stops the work with an early return when `existing`.

## When something fails

- `SupportAgentService` handles failure in 4 places: it logs it and continues in all 4.

## Diagram

```mermaid
sequenceDiagram
  participant Client
  participant Controller
  participant Service as SupportAgentService
  participant Store as Config/Agent Store
  participant AI as AI Provider

  Client->>Controller: Create agent / send chat message
  Controller->>Service: createAgent() or chat()
  Service->>Store: Load configuration and agent details
  Store-->>Service: Config and agent data

  alt Agent management
    Service->>Store: Persist agent changes
    Store-->>Service: Saved agent
  else Chat request
    Service->>AI: Send context and message
    AI-->>Service: Response or token stream
    Service->>Store: Save chat history
  end

  Service-->>Controller: Result
  Controller-->>Client: API response
```

## Usage

```ts
import { Injectable } from '@nestjs/common';
import { SupportAgentService } from './support-agent.service';

@Injectable()
export class SupportController {
  constructor(
    private readonly supportAgentService: SupportAgentService,
  ) {}

  async createAndChat() {
    const agent = await this.supportAgentService.createAgent({
      name: 'Billing Support',
      description: 'Assists customers with invoices and payments.',
    });

    const response = await this.supportAgentService.chat({
      agentId: agent.id,
      message: 'How can I download my latest invoice?',
    });

    return response;
  }

  async getConversation(agentId: string, conversationId: string) {
    return this.supportAgentService.getChatHistory({
      agentId,
      conversationId,
    });
  }
}
```

## AI Coding Instructions

- Keep agent configuration and CRUD operations routed through `SupportAgentService`; avoid duplicating persistence or validation logic in controllers.
- Load the relevant configuration and agent context before calling `chat()` or `chatStream()` so provider requests use the intended agent behavior.
- Use `chatStream()` for token-by-token responses and ensure the calling controller correctly forwards and closes the stream.
- Preserve conversation identifiers when retrieving or storing history; chat history should remain associated with the correct agent and session.
- Handle missing agents, invalid configuration, and upstream AI-provider failures explicitly when extending service methods.

## Relationships

- DEPENDS_ON → `PrismaService`
- DEPENDS_ON → `AzureSearchService`
- DEPENDS_ON → `LanguageDetectorService`
- DEPENDS_ON → `AgentAdapterService`

## Referenced By

- `PublicProjectController` (DEPENDS_ON)
- `SupportAgentController` (DEPENDS_ON)
- `SupportAgentModule` (MODULE_PROVIDES)
- `SupportAgentModule` (MODULE_EXPORTS)
