이 사례 연구에서는 기존 AI 스토리 SaaS인 StoryShelf를 AgentChat에 연결한다. 사용자는 대화를 통해 스토리를 만들고, 에이전트는 StoryShelf API를 통해 구조화된 스토리 및 챕터 레코드를 작성하고, 일러스트레이션 작업을 시작하며, 반환된 이미지 URL을 확인한 뒤 스토리를 업데이트한다. 그러면 StoryShelf는 자체 데이터베이스를 읽고 일반 라이브러리와 편집기에 결과를 표시한다.
중요한 점은 AgentChat이 스토리 데이터베이스가 되는 것이 아니며 StoryShelf가 긴 어시스턴트 응답을 레코드로 파싱하는 것도 아니라는 것입니다. 에이전트는 StoryShelf 애플리케이션이 이미 이해하는 것과 동일한 통제된 작업을 수행합니다.
1단계: StoryShelf 기능 팩 노출
POST /v1/stories
GET /v1/stories/{story_id}
POST /v1/stories/{story_id}/chapters
PUT /v1/stories/{story_id}/chapters/{chapter_id}
POST /v1/image-jobs
GET /v1/image-jobs/{job_id}
PUT /v1/stories/{story_id}/cover 각 생성 응답은 안정적인 ID를 반환합니다. 스토리와 챕터 쓰기 작업은 client_request_id를 사용해 멱등성을 보장하므로 재시도해도 중복 항목이 생성되지 않습니다. 이미지 작업은 비동기이며 poll_after_seconds를 반환합니다. 완료된 이미지 응답에는 asset_id와 image_url이 포함되며 base64 데이터는 절대 포함되지 않습니다.
2단계: StoryShelf 문서 프로비저닝
POST /api/api-documents
Authorization: Bearer ac_live_AGENT_CHAT_KEY
Content-Type: application/json
{
"title": "StoryShelf Story and Illustration API",
"description": "Create stories and chapters, generate illustrations, and attach image assets.",
"content": "# StoryShelf API\nBase URL: https://stories.example.com/v1\n\nCreate the story record before chapters and preserve every returned ID. Write chapters one at a time.\n\nPOST /stories body: client_request_id, title, audience, style, premise, outline[]. Response: story_id, status.\n\nPOST /stories/{story_id}/chapters body: client_request_id, position, title, content. Response: chapter_id, revision.\n\nPOST /image-jobs body: client_request_id, story_id, chapter_id optional, prompt, aspect_ratio. Response: job_id, status, poll_after_seconds. Start the job in one turn; sleep and poll in a later turn.\n\nGET /image-jobs/{job_id} returns status and, when succeeded, asset_id and image_url. Call view_image when visual inspection is useful.\n\nPUT /stories/{story_id}/cover body: asset_id.\n\nNever publish a draft unless the user explicitly asks."
} 문서에는 OpenAPI 경로 목록만으로는 안정적으로 추론할 수 없는 워크플로 규칙이 포함되어 있습니다. ID를 보존하고, 비동기 턴을 분리하며, 이미지 URL을 검사하고, 암묵적으로 게시하지 않는 규칙입니다.
3단계: 사용자의 스토리 세션 생성
POST /api/agent/sessions
Authorization: Bearer ac_live_AGENT_CHAT_KEY
Content-Type: application/json
{
"title": "Story creator for user_88",
"llm_config_id": "creative_model_uuid",
"api_document_ids": ["story_api_document_uuid"],
"system_prompt": "Help the user plan and create stories. Save approved creative work through StoryShelf APIs. Keep the user informed when image jobs are running.",
"max_turns": 25,
"tool_timeout_seconds": 180,
"tool_result_max_chars": 12000,
"host_headers": [
{ "host": "stories.example.com", "header_key": "Authorization", "header_value": "Bearer short_lived_story_user_token" }
]
} StoryShelf는 백엔드에서 이 세션을 생성하고 반환된 세션 UUID를 사용자의 대화 옆에 저장합니다. 수명이 짧은 헤더는 모든 스토리 API 읽기 및 쓰기를 user_88로 제한합니다. 이 헤더는 요청 시 주입되며 LLM 컨텍스트나 AgentChat API 응답에는 포함되지 않습니다.
4단계: 사용자가 채팅을 통해 생성하도록 하기
POST /api/agent/sessions/session_uuid/chat
Authorization: Bearer ac_live_AGENT_CHAT_KEY
Content-Type: application/json
{
"message": "Create a three-chapter story for ages 8-10 about a child who repairs a lighthouse for lost spaceships. Use a gentle watercolor style and make an illustrated cover."
} AgentChat은 사용자 메시지를 저장하고 processing을 반환합니다. StoryShelf UI는 채팅 요청을 열린 상태로 유지하는 대신 즉시 메시지 폴링을 시작합니다.
구체적인 도구 호출 순서
- 에이전트는 제목, 전제, 대상 독자, 스타일 및 3부 구성 개요를 계획합니다.
- POST /stories를 호출하고 story_id story_123을 받습니다.
- 각기 별도의 API 호출을 통해 1장, 2장, 3장을 작성하고 각 chapter_id를 보존합니다.
- 저장된 스토리 스타일에 맞는 이미지 프롬프트를 생성하고 POST /image-jobs를 호출합니다.
- 작업은 비동기적으로 완료되어야 하므로 다음 모델 턴에서 poll_after_seconds를 사용해 sleep을 호출한 후, 나중 요청에서 GET /image-jobs/job_7을 폴링합니다.
- 응답에 image_url이 포함되면 에이전트는 view_image를 호출하여 일러스트를 네이티브 멀티모달 입력으로 컨텍스트에 포함합니다.
- 이미지가 스토리와 일치하면 asset_id와 함께 PUT /stories/story_123/cover를 호출합니다. 일치하지 않으면 수정된 프롬프트를 새 작업으로 제출합니다.
- 저장된 스토리 ID, 장 요약, 표지 상태를 표시하며 완료합니다.
도구 결과는 완료되는 대로 영속화되지만, 다음 모델 요청에는 동시에 실행된 도구 결과가 원래 도구 호출 순서대로 전달됩니다. 한 호출에 다른 호출이 반환한 ID가 필요한 경우 같은 병렬 배치에서 종속된 쓰기를 수행하지 않도록 API 문서에서 권고해야 합니다.
5단계: AgentChat 메시지를 올바르게 병합하기
GET /api/agent/sessions/session_uuid/messages?after_id=msg_uuid&after_revision=6
Authorization: Bearer ac_live_AGENT_CHAT_KEY StoryShelf 클라이언트는 revision이 증가한 경우에만 메시지를 교체합니다. 어시스턴트 텍스트, 간략한 일러스트레이션 작업 활동, 최종 이미지 미리보기를 렌더링할 수 있습니다. 실패한 부분 어시스턴트 메시지는 계속 표시되지만 AgentChat에 의해 향후 LLM 컨텍스트에서는 제외됩니다.
이미지 생성으로 남은 턴 예산이 사용되면 AgentChat은 next_action이 continue인 상태를 반환합니다. StoryShelf는 계속 버튼을 표시하고 POST /api/agent/sessions/session_uuid/continue를 호출합니다. 새 실행에는 새로운 턴 예산이 제공되며, 영속 메시지부터 계속 진행합니다.
6단계: StoryShelf 데이터베이스에서 스토리 렌더링하기
POST /stories, POST /chapters 및 PUT /cover가 이미 검증된 레코드를 StoryShelf에 기록했습니다. 라이브러리 페이지는 StoryShelf 테이블을 조회하여 새 제목과 표지를 표시합니다. 편집기는 story_id로 챕터를 불러옵니다. 채팅 대화 기록을 파싱하여 스토리를 재구성하지는 않습니다.
이 설계는 부분 완료를 안전하게 처리할 수 있도록 합니다. 표지 작업이 실패하더라도 세 개의 챕터는 그대로 존재합니다. 사용자는 동일한 AgentChat 세션을 계속 진행하여 스토리를 다시 생성하지 않고 새 표지를 요청할 수 있습니다.
출시 전에 테스트해야 할 사항
- 동일한 client_request_id를 사용하여 스토리 및 챕터 생성을 재시도하고 중복 레코드가 나타나지 않는지 확인합니다.
- 이미지 작업 실패를 반환하고 에이전트가 스토리를 유지하며 복구 가능한 단계를 설명하는지 확인합니다.
- 이미지 폴링 중 중지한 다음 세션을 계속하고 표지를 완성합니다.
- 주입된 토큰으로 다른 사용자의 스토리 ID를 읽으려고 시도하고 StoryShelf가 403 또는 찾을 수 없음 응답을 반환하는지 확인합니다.
- 유효하지 않은 이미지 URL을 반환하고 에이전트가 이를 텍스트로 삽입하는 대신 도구 오류를 보고하는지 확인합니다.
- 완료된 각 변경 작업 후 자체 데이터베이스에서 StoryShelf 라이브러리를 새로 고칩니다.