e80a82bef4
- 更新 http-error-codes, user-points-chat-data-protocol - 更新 divination-run-protocol, profile-protocol - 删除废弃的后端和前端设计计划文档
11 KiB
11 KiB
Divination Run Protocol (Frontend <-> Backend)
This document defines the structured contract for divination run input, backend hexagram derivation, and run event output.
Protocol verification status:
- Backend route source:
backend/src/v1/agent/router.py - Backend derivation source:
backend/src/core/divination/derivation.py - Runtime payload schema source:
backend/src/schemas/domain/divination.py
Compatibility strategy
- Run/events contract:
backward-compatibleadditive evolution. - History contract (
GET /agent/history) currentlyrequires-migration(see migration notes in this document). - Existing required fields cannot be removed or renamed without migration notes.
- Canonical divination terminology values must remain Chinese.
Route overview
- Submit run:
POST /api/v1/agent/runs - Stream events:
GET /api/v1/agent/runs/{threadId}/events?runId=... - History snapshot:
GET /api/v1/agent/history - Delete session:
DELETE /api/v1/agent/sessions/{threadId} - Audio transcribe:
POST /api/v1/agent/transcribe
Run request contract
RunAgentInput uses AG-UI shape. This protocol constrains two sections:
messages[0].content(question text)forwardedProps.divinationPayload(structured divination input)
Required request shape
{
"threadId": "uuid",
"runId": "run_20260403_xxx",
"state": {},
"messages": [
{
"id": "msg_run_20260403_xxx_user_0",
"role": "user",
"content": "我最近换工作是否合适?"
}
],
"tools": [],
"context": [],
"forwardedProps": {
"runtime_mode": "chat",
"client_time": {
"device_timezone": "Asia/Shanghai",
"client_now_iso": "2026-04-03T20:30:00+08:00",
"client_epoch_ms": 1775219400000
},
"divinationPayload": {
"divinationMethod": "手动起卦",
"questionType": "事业",
"question": "我最近换工作是否合适?",
"divinationTimeIso": "2026-04-03T20:30:00+08:00",
"yaoLines": [
"少阳",
"少阴",
"老阳",
"少阴",
"少阳",
"老阴"
]
}
}
}
AG-UI required base fields
state: required object, frontend sends{}by default.messages[0].id: required string id for user message.tools: required array, frontend sends empty array when no tools requested.context: required array, frontend sends empty array when no extra context.
divinationPayload strict rules
divinationMethod: enum, allowed values手动起卦 | 自动起卦questionType: non-empty string, recommended Chinese category labelsquestion: non-empty stringdivinationTimeIso: RFC3339 datetime with timezone offsetyaoLines: exactly 6 items, order is初爻 -> 上爻yaoLinesitem enum:少阳 | 少阴 | 老阳 | 老阴- Additional fields are forbidden.
runtime_mode rules
- Allowed values:
chat | follow_up. chat: first run for a session.follow_up: follow-up run in existing session.- Missing or invalid
runtime_modeMUST return422with codeAGENT_RUNTIME_MODE_INVALID. - Current backend behavior still requires
forwardedProps.divinationPayloadin both modes.
Follow-up request note
- Follow-up submit still uses
POST /api/v1/agent/runs. - Required differences from first run:
threadIdmust be existing session id.forwardedProps.runtime_modemust befollow_up.messages[0].contentis follow-up question text.- If
threadIddoes not exist, backend returns404(AGENT_SESSION_NOT_FOUND).
Event output contract
During run streaming, backend emits standard AG-UI lifecycle events and two divination-relevant payload events:
- Lifecycle:
RUN_STARTED,RUN_FINISHEDorRUN_ERROR. - Step events:
STEP_STARTED,STEP_FINISHEDwithstepName(for example:worker). - Payload events:
DIVINATION_DERIVED,TEXT_MESSAGE_END.
1) DIVINATION_DERIVED
- Emitted once after backend derives hexagram data.
- Payload field:
divination(strict object). - Emitted only when
runtime_mode=chat.
divination object:
{
"question": "我最近换工作是否合适?",
"questionType": "事业",
"divinationMethod": "手动起卦",
"divinationTime": "2026年04月03日 20:30",
"binaryCode": "101001",
"changedBinaryCode": "100001",
"guaName": "山火贲",
"upperName": "艮",
"lowerName": "离",
"targetGuaName": "山雷颐",
"worldPosition": 1,
"responsePosition": 4,
"hasChangingYao": true,
"ganzhi": {
"yearGanZhi": "丙午",
"monthGanZhi": "壬辰",
"dayGanZhi": "辛亥",
"timeGanZhi": "乙巳",
"yearKongWang": "子丑",
"monthKongWang": "午未",
"dayKongWang": "寅卯",
"timeKongWang": "戌亥",
"yueJian": "辰土",
"riChen": "亥水",
"yuePo": "戌土",
"riChong": "巳火"
},
"wuXingStatuses": {
"木": "囚",
"火": "休",
"土": "旺",
"金": "相",
"水": "死"
},
"yaoInfoList": [
{
"position": 1,
"spiritName": "虎",
"relationName": "官鬼",
"tiganName": "卯",
"elementName": "木",
"isYang": true,
"isChanging": false,
"specialMark": "世"
}
],
"targetYaoInfoList": [],
"fushenPositions": [2],
"fushenInfoList": [
{
"position": 2,
"relationName": "父母",
"tiganName": "午",
"elementName": "火"
}
]
}
2) TEXT_MESSAGE_END
- Standard final answer event.
runtime_mode=chatfields:status,sign_level,conclusion,focus_points,advice,keywords,answer,error,divination_derived.runtime_mode=follow_upfields:status,answer,error.runtime_mode=follow_upMUST NOT includesign_level,conclusion,focus_points,advice,keywords,divination_derived.- Language rule:
conclusion,focus_points,advice,keywords,answershould follow userai_languagepreference unless user explicitly requests otherwise. - Canonical six-yao terms remain Chinese in protocol text (for example: 世爻、应爻、动爻、静爻、六亲、六神、伏神、月建、日辰、月破、日冲、空亡、五行旺衰).
Frontend should combine:
- structural divination data from
DIVINATION_DERIVED - interpretation text from
TEXT_MESSAGE_END
History snapshot contract
GET /api/v1/agent/history is the canonical replay source for frontend history list and result reconstruction.
- When
threadIdis provided, backend returns full session messages ordered byseq asc. - When
threadIdis omitted, backend returns one latest assistant message per session for history list summary. threadIdis the session identifier (same value as AG-UI run/events path parameter).
Required response shape
{
"scope": "history_session_full",
"threadId": "uuid|null",
"day": null,
"hasMore": false,
"messages": [
{
"id": "uuid",
"threadId": "session-uuid",
"seq": 12,
"role": "assistant",
"content": "...",
"timestamp": "2026-04-05T12:34:56+00:00",
"agent_output": {
"status": "success",
"sign_level": "中上签",
"conclusion": ["..."],
"focus_points": ["..."],
"advice": ["..."],
"keywords": ["..."],
"answer": "...",
"divination_derived": {
"binaryCode": "101001",
"changedBinaryCode": "100001",
"guaName": "山火贲"
}
}
},
{
"id": "uuid",
"threadId": "session-uuid",
"seq": 11,
"role": "user",
"content": "我最近换工作是否合适?",
"timestamp": "2026-04-05T12:34:12+00:00",
"attachments": [
{
"mimeType": "image/png",
"url": "https://...signed..."
}
]
}
]
}
Rules:
scope=history_session_fullmeans full-thread replay withmessagesordered byseq.scope=history_sessions_latest_assistantmeans cross-session summary list.- Each
messages[i].threadIdis required and points to the owning session. Frontend must use this value to open detail replay and follow-up. dayandhasMoreare retained for compatibility with old clients, but inhistory_session_fullmode backend currently returnsday=nullandhasMore=false.- In
history_sessions_latest_assistant, backend computeshasMorefromsession_limit + 1query. assistantmessage MUST provideagent_outputwhen backend has valid worker output metadata.agent_output.divination_deriveduses the same shape asDIVINATION_DERIVED.divinationpayload.- Frontend reconstructs divination result page from
agent_outputdata, not from local mock data. agent_output.sign_levelallowed values:上上签/中上签/中下签/下下签.
Migration note (requires-migration)
Change set
GET /agent/history?threadId=...now returns full session replay (scope=history_session_full) instead of day-window snapshot semantics.messages[i].threadIdis now required.ui_schemais removed from history payload.runtime_mode=follow_upuses minimalTEXT_MESSAGE_ENDschema and no longer emitsDIVINATION_DERIVED.- Added
DELETE /api/v1/agent/sessions/{threadId}with idempotent204 No Content(already deleted or not found also returns 204).
Frontend migration steps
- Parse history as ordered message stream by
messages[].seq. - Use
messages[].threadIdas session id for opening follow-up. - Do not depend on
ui_schemain history payload. - Keep
day/hasMoreoptional-read only; do not use them for pagination in thread replay mode.
Rollback notes
- If backend rolls back to day-window semantics, frontend must switch detail replay back to day-based load logic and stop requiring
messages[].threadId. - Keep legacy parser branch behind feature flag during staged rollout.
Error contract linkage
- All errors use RFC7807 with extension
codeand optionalparams. - Error code registry source:
docs/protocols/common/http-error-codes.md.
Session delete contract
DELETE /api/v1/agent/sessions/{threadId}
- Authorization: current user must own the session.
- Semantics: soft delete session (
deleted_at), history reads filter deleted sessions by default. - Success:
204 No Content. - Idempotent: already deleted or not found also returns
204 No Content.
Transcribe contract
POST /api/v1/agent/transcribe
Request:
multipart/form-data- field name:
audio - allowed content types:
audio/wav,audio/x-wav,audio/wave - max payload bytes:
10MB
Response:
{
"transcript": "我今天适合出门谈合作吗?"
}
Error codes (see common registry):
AGENT_AUDIO_UNSUPPORTED_FORMATAGENT_AUDIO_TOO_LARGEAGENT_AUDIO_EMPTYAGENT_ASR_UNAVAILABLE