AgentChat
← 모든 글
아키텍처·10분 읽기

이미 보유한 API를 사용하여 SaaS에 AI 에이전트를 추가하는 방법

각 작업마다 맞춤형 도구를 구축하지 않고도 기존 제품 API를 안전한 에이전트 기능으로 전환하는 실용적인 아키텍처입니다.

이 가이드에서는 SupportFlow라는 가상의 SaaS를 위한 완전한 AgentChat 통합을 구현합니다. SupportFlow에는 이미 연체된 청구서를 찾고, 알림을 보내고, 계정 메모를 추가하는 API가 있습니다. 이러한 API를 AgentChat에 프로비저닝하고, 사용자 범위의 채팅을 생성하고, 비동기 에이전트 실행을 시작한 다음, 영속화된 메시지와 SupportFlow 자체 데이터베이스에서 결과를 렌더링합니다.

중요한 아키텍처 경계는 명확합니다. AgentChat은 모델 추론, 도구 선택, 채팅 기록 및 실행 제어를 담당합니다. SupportFlow는 계속해서 고객, 청구서, 권한 부여, 검증 및 최종 비즈니스 기록을 관리합니다. API 문서가 두 시스템을 연결합니다.

모든 SaaS 기능을 에이전트 런타임에 추가할 필요는 없습니다. 소수의 핵심 비즈니스 작업을 HTTP API로 노출하고, 각 채팅에 해당 계약을 프로비저닝하면 됩니다.

완료된 요청 흐름

  1. SupportFlow는 대시보드에서 AgentChat API 키 하나를 생성하고 이를 백엔드에만 저장합니다.
  2. 백엔드는 POST /api/api-documents를 사용하여 SupportFlow 작업을 등록합니다.
  3. 사용자가 어시스턴트를 열면 SupportFlow는 문서 UUID, LLM 구성 UUID, 그리고 API 호스트용 쓰기 전용 사용자 자격 증명을 사용해 세션을 생성합니다.
  4. SupportFlow는 사용자 메시지를 POST /api/agent/sessions/{id}/chat으로 전송합니다.
  5. AgentChat은 첨부된 계약서를 읽고 내장된 http_request 도구를 사용하여 SupportFlow를 호출합니다.
  6. SupportFlow가 AgentChat 메시지를 폴링하는 동안 일반 UI는 SupportFlow 데이터베이스에서 청구서와 메모를 읽습니다.

1단계: 범위가 좁은 비즈니스 작업 노출

에이전트에는 데이터베이스 액세스나 거대한 단일 내부 API가 필요하지 않습니다. 이 워크플로에서 SupportFlow는 테넌트를 인식하는 엔드포인트를 정확히 세 개 노출합니다:

GET /v1/invoices?status=overdue&limit=3
→ { "items": [{ "invoice_id": "inv_72", "account_id": "acct_9", "amount": 480, "currency": "USD", "due_at": "2026-08-01" }] }

POST /v1/reminders
{ "invoice_id": "inv_72", "tone": "friendly" }
→ { "reminder_id": "rem_31", "status": "queued" }

POST /v1/accounts/acct_9/notes
{ "body": "Friendly reminder queued for overdue invoice inv_72." }
→ { "note_id": "note_55", "created_at": "2026-08-23T09:30:00Z" }

각 엔드포인트는 호출자를 인증하고, 자격 증명에서 테넌트를 도출한 다음 모든 데이터베이스 작업에 필터를 적용합니다. 한 호출에서 반환된 ID는 다음 호출의 안전한 입력값이 됩니다. 모델은 데이터베이스 비밀번호나 제한 없는 쿼리 인터페이스를 전달받지 않습니다.

2단계: 모델 구성을 한 번 생성하기

모든 AgentChat 세션에는 사용자가 소유한 LLM 구성이 필요합니다. SupportFlow는 대시보드 또는 API를 통해 구성을 생성하고 반환된 UUID를 보관할 수 있습니다.

POST $AGENTCHAT_SITE_URL/api/llm-config
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "name": "Support production model",
  "api_url": "https://llm-provider.example.com/v1/chat/completions",
  "api_key": "provider_secret",
  "model": "provider-model-name",
  "max_context_length": 128000,
  "max_output_tokens": 8192,
  "temperature": 0.2,
  "disable_reasoning": false
}

응답은 success와 data로 래핑됩니다. 채팅 생성 시 사용할 llm_config_id로 data.id를 저장하세요. AgentChat은 구성을 다시 읽어올 때 제공업체 키를 마스킹합니다.

3단계: SupportFlow API 문서 프로비저닝하기

이것이 플러그인 메커니즘입니다. 이 문서에는 운영 지침, 정확한 입력값, 정확한 출력값, 실행 순서 규칙이 포함됩니다. 마케팅 문구도 아니며, 에이전트가 추측하도록 만드는 링크도 아닙니다.

POST $AGENTCHAT_SITE_URL/api/api-documents
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "SupportFlow Invoice Actions",
  "description": "Find overdue invoices, queue reminders, and record account notes.",
  "content": "# SupportFlow Invoice Actions\nBase URL: https://support.example.com/v1\n\nGET /invoices?status=overdue&limit=3 returns items with invoice_id, account_id, amount, currency, and due_at. Use only when the user requests invoice lookup.\n\nPOST /reminders body: invoice_id required; tone is friendly or firm. Response: reminder_id and status. Never send more reminders than the user requested.\n\nPOST /accounts/{account_id}/notes body: body required. Call only after the reminder request succeeds. Include the invoice ID and reminder status in the note.\n\nIf any write returns 401 or 403, stop writing and explain that the session credential needs access. Do not retry a permission denial."
}

AgentChat은 UUID를 포함한 새 문서를 data로 반환합니다. 해당 UUID를 SupportFlow의 통합 구성에 저장하세요. 세션은 문서를 복사하는 대신 첨부하므로, 나중에 이 문서를 업데이트하면 이후 채팅 턴에서 사용되는 지침이 변경됩니다.

4단계: 현재 SupportFlow 사용자를 위한 채팅 생성

POST $AGENTCHAT_SITE_URL/api/agent/sessions
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "Invoice assistant for user_42",
  "llm_config_id": "llm_config_uuid",
  "api_document_ids": ["supportflow_document_uuid"],
  "system_prompt": "Act only on the user’s explicit request. Summarize every write with the affected invoice and account IDs.",
  "compact_threshold_percent": 80,
  "max_turns": 12,
  "tool_timeout_seconds": 120,
  "tool_result_max_chars": 10000,
  "host_headers": [
    { "host": "support.example.com", "header_key": "Authorization", "header_value": "Bearer short_lived_user_42_token" },
    { "host": "support.example.com", "header_key": "X-Workspace-ID", "header_value": "workspace_7" }
  ]
}

헤더 값은 쓰기 전용입니다. AgentChat은 이 세션에 사용할 헤더 값을 저장하고, http_request가 일치하는 호스트를 대상으로 할 때만 주입하며, 그 값을 모델이나 API 응답에 노출하지 않습니다. 두 번째 SupportFlow 사용자는 동일한 문서 UUID를 사용하지만 헤더는 다른 별도의 세션을 갖게 됩니다.

5단계: 비동기 실행 시작

POST $AGENTCHAT_SITE_URL/api/agent/sessions/session_uuid/chat
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{ "message": "Find my three most overdue invoices, send each a friendly reminder, and add a note to each account." }

→ { "success": true, "data": { "session_id": "session_uuid", "state": "processing" } }

AgentChat은 즉시 반환하고 백그라운드에서 실행을 계속합니다. 에이전트는 첨부된 SupportFlow 문서와 함께 정확히 네 개의 기본 제공 도구(get_api_document, http_request, sleep, view_image)를 받습니다. SupportFlow 기능이 이러한 도구에 컴파일되어 있는 것은 아닙니다. 에이전트는 제공된 API 계약에서 해당 기능을 학습하고 http_request를 통해 실행합니다.

이 요청 중 에이전트가 수행하는 작업

  1. 문서화된 연체 송장 엔드포인트를 http_request를 통해 호출합니다.
  2. 구조화된 항목을 읽고 사용자가 요청한 송장 중 최대 세 개를 선택합니다.
  3. 알림을 대기열에 추가합니다. 하나의 모델 응답에서 생성된 독립적인 호출은 동시에 실행될 수 있습니다.
  4. 알림 결과가 성공적으로 준비되면, 반환된 각 송장 및 계정 ID를 사용하여 계정 메모 엔드포인트를 호출합니다.
  5. 완료된 작업과 송장별 오류가 있는 경우 이를 나열하는 최종 어시스턴트 메시지를 생성합니다.

이것이 응답 설계가 중요한 이유입니다. 모호한 “성공” 결과만으로는 에이전트가 다음 작업과 확실하게 연결할 수 있는 것이 아무것도 남지 않습니다. 구조화된 ID와 상태를 사용하면 추론 루프가 여러 일반 API를 조합해 하나의 사용자 결과를 만들어낼 수 있습니다.

6단계: LLM 스트림이 아니라 영속 메시지를 폴링하기

GET $AGENTCHAT_SITE_URL/api/agent/sessions/session_uuid/messages?after_id=&after_revision=0
Authorization: Bearer ac_live_AGENTCHAT_KEY

→ {
  "success": true,
  "data": {
    "messages": [{ "id": "message_uuid", "role": "assistant", "content": "...", "stream_status": "streaming", "revision": 4 }],
    "last_id": "message_uuid",
    "last_revision": 4,
    "is_processing": true,
    "total_tokens": 2840
  }
}

SupportFlow는 백엔드 또는 프록시된 클라이언트에서 1초마다 폴링하고, 메시지 ID별로 행을 병합하며, 리비전이 증가한 경우에만 콘텐츠를 교체합니다. 대화 출력의 기준 데이터는 AgentChat의 데이터베이스입니다. 인보이스, 리마인더, 메모의 기준 데이터는 계속해서 SupportFlow의 데이터베이스입니다.

is_processing이 false가 되면 SupportFlow는 인보이스 및 계정 쿼리를 새로 고칠 수 있습니다. 그러면 일반 제품 UI에 자체 API를 통해 생성된 리마인더와 메모가 표시되므로, 비즈니스 상태를 재구성하기 위해 어시스턴트의 문장을 파싱할 필요가 없습니다.

실행 제어 및 장애 복구

GET  /api/agent/sessions/session_uuid/state
POST /api/agent/sessions/session_uuid/stop
POST /api/agent/sessions/session_uuid/continue

state 엔드포인트는 처리가 활성 상태인지와 다음 작업이 continue인지 여부를 보고합니다. Stop 요청은 활성 실행을 취소합니다. 복구 가능한 오류나 최대 턴 제한으로 작업이 일시 중지된 경우, continue는 새로운 턴 예산과 동일한 영속적 대화 컨텍스트를 사용해 새 실행을 시작합니다.

프로비저닝할 것과 프로비저닝하지 않을 것

  • 검색, 생성, 업데이트, 검증, 게시 또는 작업 상태 조회와 같이 안정적인 비즈니스 기능을 나타내는 API를 프로비저닝합니다.
  • 필수 필드, 제약 조건, 응답 객체, 오류의 의미, 부작용 및 순서 요구 사항을 문서화합니다.
  • 모든 내부 엔드포인트가 아니라 채팅 경험에 필요한 문서만 연결합니다.
  • 자격 증명은 호스트별 세션 헤더에 보관하고, 프롬프트나 API 문서 내용에는 절대 포함하지 않습니다.
  • 에이전트를 유연하게 만들기 위한 목적만으로 원시 SQL, 제한 없는 파일 액세스 또는 범용 내부 프록시를 노출하지 마세요.
  • 다른 클라이언트에 적용하는 것과 정확히 동일하게 모든 도구 요청에 대해 자체 인증 및 검증을 실행합니다.

핵심 도구 세트를 늘리지 않고도 기능 범위를 확장할 수 있는 이유

RAG 제품은 검색 및 인용 엔드포인트를 프로비저닝할 수 있습니다. 스토리 제품은 챕터, 이미지 생성 및 퍼블리싱 엔드포인트를 프로비저닝할 수 있습니다. 코딩 제품은 워크스페이스 파일, 검사 및 배포 엔드포인트를 프로비저닝할 수 있습니다. AgentChat은 여전히 동일한 4개의 핵심 도구를 사용합니다. 애플리케이션별 작업은 API 문서로 제공되므로, 기능 추가는 새로운 에이전트 런타임 릴리스가 아니라 프로비저닝 변경으로 이루어집니다.

이것이 AgentChat의 핵심 패턴입니다. API 문서를 만들고, 범위가 지정된 채팅 세션을 만든 다음, 에이전트가 HTTP 작업을 조합하도록 하고, 영구 메시지를 소비하며, 그 결과로 생성된 레코드를 자체 애플리케이션 데이터베이스에서 렌더링합니다.