xiaohongshu
xiaohongshu
chat-api-orchestration
Implement single-endpoint chat API with deterministic request orchestration. This skill should be used when users need to create /api/{user_id}/chat endpoint, implement request validation, resolve conversation IDs, call agent runners, or design chat API contracts with structured responses.
Full skill instructions
Guide for implementing a single-endpoint chat API with deterministic request flow.
/api/{user_id}/chat endpoint contractGather context to ensure successful implementation:
| Source | Gather |
|---|---|
| Codebase | Existing routers, auth dependencies, error handling patterns |
| Conversation | User's agent runner interface, specific response fields needed |
| Skill References | API contract, request flow, error handling patterns |
| User Guidelines | Project conventions, existing schema patterns |
POST /api/{user_id}/chat
│
▼
┌─────────────────────────────────────────┐
│ DETERMINISTIC FLOW │
│ │
│ 1. Validate Request │
│ 2. Authenticate User │
│ 3. Resolve Conversation │
│ 4. Execute Agent │
│ 5. Return Response │
│ │
└─────────────────────────────────────────┘
| Benefit | Description |
|---|---|
| Simplicity | One URL to remember, one contract to maintain |
| Stateless | Each request is self-contained |
| Idempotent design | Can safely retry failed requests |
| Clear ownership | user_id in path ensures proper scoping |
Every request follows this exact sequence. No shortcuts, no variations.
┌─────────────────────────────────────────────────────────────┐
│ Step 1: VALIDATE REQUEST │
│ • Check required fields (message) │
│ • Validate field types and constraints │
│ • Return 400 if invalid │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Step 2: AUTHENTICATE USER │
│ • Verify JWT from Authorization header │
│ • Extract user_id from token │
│ • Verify path user_id matches token user_id │
│ • Return 401/403 if unauthorized │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Step 3: RESOLVE CONVERSATION │
│ • If conversation_id provided: load existing │
│ • If not provided: create new conversation │
│ • Verify conversation ownership │
│ • Return 404 if conversation not found │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Step 4: EXECUTE AGENT │
│ • Build context from conversation history │
│ • Add user message to context │
│ • Call agent runner with context │
│ • Persist user message + agent response │
│ • Return 503 if agent fails │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Step 5: RETURN RESPONSE │
│ • Format structured response │
│ • Include conversation_id for continuation │
│ • Return 200 with ChatResponse │
└─────────────────────────────────────────────────────────────┘
See references/api-contract.md for complete schemas.
# schemas/chat.py
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
class ChatRequest(BaseModel):
"""Incoming chat request."""
message: str = Field(..., min_length=1, max_length=10000)
conversation_id: Optional[str] = Field(
None,
description="Existing conversation ID, or omit to create new"
)
model: Optional[str] = Field("gpt-4", description="Model to use")
class ChatResponse(BaseModel):
"""Chat API response."""
conversation_id: str
message: str
role: str = "assistant"
created_at: datetime
usage: Optional[dict] = None
See references/request-flow.md for detailed implementation.
# routers/chat.py
from fastapi import APIRouter, Depends, HTTPException, status
router = APIRouter(prefix="/api", tags=["chat"])
@router.post("/{user_id}/chat", response_model=ChatResponse)
async def chat(
user_id: str,
request: ChatRequest,
current_user: AuthenticatedUser = Depends(get_current_user),
session: Session = Depends(get_session),
agent: AgentRunner = Depends(get_agent_runner)
):
"""
Single chat endpoint with deterministic flow.
1. Validate (handled by Pydantic)
2. Authenticate (handled by dependency)
3. Resolve conversation
4. Execute agent
5. Return response
"""
# Step 2: Verify user_id matches authenticated user
if user_id != current_user.user_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Cannot access another user's chat"
)
# Step 3: Resolve conversation
conversation_id = await resolve_conversation(
session=session,
user_id=user_id,
conversation_id=request.conversation_id
)
# Step 4: Execute agent
response = await execute_agent(
session=session,
agent=agent,
conversation_id=conversation_id,
user_id=user_id,
message=request.message,
model=request.model
)
# Step 5: Return response
return response
# services/conversation.py
async def resolve_conversation(
session: Session,
user_id: str,
conversation_id: Optional[str]
) -> str:
"""
Resolve or create conversation.
- If conversation_id provided: verify exists and owned by user
- If not provided: create new conversation
Returns: conversation_id (existing or new)
"""
if conversation_id:
# Load existing
conv = get_conversation(session, conversation_id, user_id)
if not conv:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Conversation not found"
)
return conv.id
else:
# Create new
conv = create_conversation(session, user_id=user_id)
return conv.id
# services/agent.py
async def execute_agent(
session: Session,
agent: AgentRunner,
conversation_id: str,
user_id: str,
message: str,
model: str
) -> ChatResponse:
"""
Execute agent with conversation context.
1. Load conversation history
2. Add user message
3. Call agent
4. Persist response
5. Return structured response
"""
# Load context
history = get_messages(session, conversation_id, user_id)
context = [{"role": m.role, "content": m.content} for m in history]
# Add user message
add_message(session, conversation_id, user_id, "user", message)
context.append({"role": "user", "content": message})
try:
# Call agent
result = await agent.run(messages=context, model=model)
# Persist response
add_message(session, conversation_id, user_id, "assistant", result.content)
return ChatResponse(
conversation_id=conversation_id,
message=result.content,
role="assistant",
created_at=datetime.now(timezone.utc),
usage=result.usage
)
except AgentError as e:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"Agent error: {str(e)}"
)
See references/error-handling.md for complete patterns.
| Step | Error | Status | Response |
|---|---|---|---|
| 1. Validate | Invalid request | 400 | {"detail": "Field X is required"} |
| 2. Auth | Missing token | 401 | {"detail": "Authentication required"} |
| 2. Auth | Wrong user | 403 | {"detail": "Cannot access another user's chat"} |
| 3. Resolve | Conv not found | 404 | {"detail": "Conversation not found"} |
| 4. Execute | Agent fails | 503 | {"detail": "Agent error: ..."} |
| * | Unexpected | 500 | {"detail": "Internal server error"} |
For safe retries, consider adding request deduplication:
class ChatRequest(BaseModel):
message: str
conversation_id: Optional[str] = None
request_id: Optional[str] = Field(
None,
description="Client-generated UUID for idempotency"
)
If request_id was seen recently, return cached response instead of re-executing.
Before delivering implementation:
| File | When to Read |
|---|---|
references/api-contract.md | Complete request/response schemas and examples |
references/request-flow.md | Detailed implementation of each step |
references/error-handling.md | Error codes, formats, and recovery patterns |
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience