Agent 및 자동화
AI 코딩 Agent, 백엔드 워커, 미디어 파이프라인을 위한 운영 연동 가이드입니다.
복사 가능한 참조 클라이언트
모델 검색, 작업 생성, 실패한 작업 재시도, 상태 조회, 모든 종료 상태, 제한된 대기, 멱등성과 오류 처리를 포함한 무의존성 예제입니다. 수락된 작업은 취소할 수 없습니다.
문서 예제이며 출시된 npm/PyPI 패키지가 아닙니다. 10분은 로컬 대기 한도이지 운영 SLA가 아닙니다.
AI 코딩 Agent나 자동화 백엔드가 SpicyAPI를 연동할 때 사용하는 실전 가이드입니다. API 사양 확인, 입력 검증, 단 한 번의 생성 요청, 안전한 대기, 완료 확인, 만료 전 결과 보관을 제한 시간과 복구 지점이 있는 흐름으로 만듭니다.
API 키는 서버에만 보관하세요
SPICY_API_KEY를 브라우저 JavaScript, 모바일 앱, 공개 프롬프트, 저장소 또는 Agent 대화 기록에 넣지 마세요. UI는 자체 백엔드를 호출하고, 백엔드가 SpicyAPI를 호출해야 합니다. Agent에는 키 값이 아니라 SPICY_API_KEY 같은 시크릿 참조만 제공하세요.
기계가 읽을 수 있는 탐색 경로
현재 질문에 답하는 가장 작은 문서부터 읽으면 컨텍스트 비용과 오래된 정보의 위험을 함께 줄일 수 있습니다.
| 경로 | 용도 |
|---|---|
/agent.md | 짧은 연동 정책과 안전한 기본 흐름 |
/llms.txt | 제품, 모델, 문서의 공개 색인 |
/llms-full.txt | 짧은 색인보다 넓은 검색 문맥이 필요할 때 |
/api/agent | 도구와 자동 클라이언트용 구조화 JSON 매니페스트 |
/openapi.yaml | 요청과 응답 형식의 기준 스냅샷 |
OpenAPI와 최신 모델 카탈로그를 구현 기준으로 사용하세요. 마케팅 예시는 Schema가 아닙니다. 코드를 생성하기 전이나 검증 오류가 새로 발생하면 캐시된 탐색 문서를 갱신하세요.
공식 npm 통합
SDK, CLI, MCP와 범용 Agent Skill은 각각 독립된 MIT 라이선스 npm 패키지입니다. 필요한 패키지만 설치하세요. @spicyapi/skill은 이식 가능한 Agent Skills 형식이며 Codex 전용이 아닙니다.
npm install @spicyapi/sdk
npx --yes --package=@spicyapi/cli spicyapi --help
npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx --yes --package=@spicyapi/skill spicyapi-skill installSkill은 기본적으로 ~/.agents/skills/spicyapi에 설치됩니다. 다른 Skills 디렉터리를 쓰는 Agent에서는 --target /정확한/경로/spicyapi를 지정하세요.
코딩 에이전트에서 사용하기
MCP 서버는 로컬에서 stdio로 실행되며 모델 카탈로그, 견적, 작업 생성, 결과 조회를 에이전트에 넘깁니다. 과금되는 동작은 반드시 확인을 거치며 에이전트가 건너뛸 수 없습니다. 아래는 각 클라이언트가 현재 권장하는 형태입니다. 설정 위치와 형식은 클라이언트가 정하고 버전마다 달라지므로 최종 기준은 각 제품의 공식 문서입니다.
Claude Code
claude mcp add spicyapi \
-e SPICY_API_KEY=$SPICY_API_KEY \
-- npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx --yes --package=@spicyapi/skill spicyapi-skill install \
--target ~/.claude/skills/spicyapiCodex CLI
codex mcp add spicyapi \
--env SPICY_API_KEY=$SPICY_API_KEY \
-- npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx --yes --package=@spicyapi/skill spicyapi-skill install \
--target ~/.codex/skills/spicyapi두 명령 모두 현재 셸의 SPICY_API_KEY를 해당 클라이언트의 로컬 설정에 기록합니다. 키를 export 해 둔 터미널에서 실행하세요. 키는 로컬에만 남으며 커밋하면 안 됩니다.
Cursor, Windsurf, Gemini CLI
설정 파일은 각각 ~/.cursor/mcp.json, ~/.codeium/windsurf/mcp_config.json, ~/.gemini/settings.json이며 형식은 동일합니다.
{
"mcpServers": {
"spicyapi": {
"command": "npx",
"args": ["--yes", "--package=@spicyapi/mcp", "spicyapi-mcp"],
"env": { "SPICY_API_KEY": "YOUR_SERVER_SIDE_KEY" }
}
}
}모두 저장소 밖에 있는 사용자 설정 파일입니다. YOUR_SERVER_SIDE_KEY를 실제 키로 바꾼 뒤에는 이 블록을 커밋되는 프로젝트 파일에 복사하지 마세요.
VS Code
.vscode/mcp.json은 저장소와 함께 커밋되므로 키를 넣으면 안 됩니다. VS Code가 서버를 처음 시작할 때 값을 묻고 자체 보안 저장소에 보관하도록 하세요.
{
"inputs": [
{
"id": "spicyapi-key",
"type": "promptString",
"description": "SpicyAPI key",
"password": true
}
],
"servers": {
"spicyapi": {
"type": "stdio",
"command": "npx",
"args": ["--yes", "--package=@spicyapi/mcp", "spicyapi-mcp"],
"env": { "SPICY_API_KEY": "${input:spicyapi-key}" }
}
}
}연결한 다음
바로 실제 작업을 시켜 보세요.
SpicyAPI로 호출할 수 있는 이미지 모델을 나열하고, 저렴한 것을 골라 야경 인물 사진을 한 장 생성한 다음 완료되면 결과 링크를 알려 줘.
에이전트는 카탈로그를 읽고 해당 모델의 스키마를 가져와 정확한 견적을 받은 뒤, 과금 전에 반드시 확인을 요청합니다. Skill까지 설치하면 하나의 멱등 키를 계속 사용하고, 반복 폴링 대신 준비된 결과 링크를 읽습니다.
운영 워크플로
- 모델과 입력 Schema를 확정합니다. 원하는 모달리티의 엔드포인트를 고르고 현재 Schema로 입력을 검증합니다. 필드명을 추측하거나 알 수 없는 필드를 조용히 버리지 않습니다.
- 한 번만 생성합니다. 논리적 생성 요청마다 안정적인
Idempotency-Key를 만들고 첫 호출 전에 저장합니다. 모든 재시도는 같은 값을 써야 합니다. 멱등성을 참고하세요. taskId를 즉시 저장합니다. 상태 조회, Webhook 대조, 지원, 과금 조사에 쓰이는 영구 식별자입니다. 재시도에서 같은 ID가 오더라도 로컬 레코드를 추가하지 마세요.- 상한을 두고 기다립니다. 서명된 Webhook을 우선 사용합니다. 폴링이 필요하면 약 2초에서 시작해 1.5배씩 늘리고 15초에서 제한하며, 전체 제한 시간도 둡니다.
succeeded,failed,canceled,expired는 종료 상태입니다. - 검증 후 콜백을 처리합니다.
X-Webhook-Timestamp, 원본 요청 본문의 다이제스트, HMAC을 검증하고 전송request_id로 중복을 제거합니다. 빠르게 2xx로 응답한 뒤 작업 큐에서 처리합니다. 자세한 내용은 Webhooks에 있습니다. - 결과를 제때 복사합니다. 객체 키를 서명 URL로 교환하고 보관할 결과를 자체 스토리지로 복사하세요. URL은 현재 20분 뒤 만료됩니다. 미디어와 보관 정책도 확인하세요.
POST /api/v1/jobs/createTask
Authorization: Bearer $SPICY_API_KEY
Content-Type: application/json
Idempotency-Key: project-42-scene-07-v1const deadline = Date.now() + 10 * 60_000;
let delay = 2_000;
while (Date.now() < deadline) {
await sleep(delay);
const task = await recordInfo(taskId);
if (['succeeded', 'failed', 'canceled', 'expired'].includes(task.state)) return task;
delay = Math.min(Math.round(delay * 1.5), 15_000);
}
throw new Error(`task ${taskId} exceeded the polling deadline`);로컬 제한 시간 초과는 생성 실패의 증거가 아닙니다. taskId를 보관하고 나중에 다시 대조하세요. HTTP 200만으로 성공을 판단하지 말고 반드시 data.state를 읽어야 합니다.
최소 영구 레코드
재시작 후 안전하게 이어갈 수 있도록 localRequestId, idempotencyKey, taskId, model, state, lastCheckedAt, webhookDeliveryId, outputKeys를 저장합니다. 만료되는 다운로드 URL을 영구 자산 ID로 사용하지 마세요.
Mock 및 인수 테스트
비동기 작업, Webhooks, 오류의 응답 형식으로 로컬 계약 Mock을 만드세요. 다음 경우를 반드시 포함합니다.
- queued → running → succeeded, 그리고
code: 200이지만data.state: "failed"인 종료 실패 - 중복 생성이 같은
taskId를 반환하는 경우 - 정상 서명, 잘못된 서명, 같은 Webhook의 재전송
429,503, 네트워크 타임아웃, 폴링 전체 제한 시간 초과- 만료된 다운로드 URL 재발급
Mock은 오케스트레이션만 검증합니다. 출시 전에는 동일한 운영 모델과 입력 구조로 작은 실제 작업을 실행하세요.
출시 인수 체크리스트
- 비밀은 서버 측 비밀 저장소에만 있고 로그에서 마스킹됩니다.
- 현재 모델 Schema를 읽으며 필드를 추측하지 않습니다.
- 논리 요청 하나마다 저장된
Idempotency-Key가 하나뿐입니다. - 후속 처리 전에
taskId를 저장하고 프로세스 재시작 후 복원할 수 있습니다. - 폴링에 백오프, 최대 간격, 전체 제한 시간이 있습니다.
- Webhook은 시각, 원문 본문, HMAC을 검증하고 전송 ID로 중복을 제거합니다.
- 성공 여부는 HTTP 상태가 아니라
data.state로 판단합니다. - URL 또는 보관 기간 만료 전에 결과를 복사하고 객체 키를 영구 참조로 씁니다.
-
request_id,taskId, 모델, 시도 횟수만 기록하고 비밀과 전체 프롬프트는 기록하지 않습니다.
Agent의 완료 보고서에는 선택 모델, Schema 조회 시각, 멱등성 전략, 폴링 제한 시간, Webhook 검증 방식, 완료된 체크리스트가 포함되어야 합니다.

