Yapay Zeka Mesajları
Bir oturum içindeki mesajlar. Bir kullanıcı mesajı göndermek, asistan yanıtını oluşturan bir yapay zeka çalışmasını tetikler.
Sohbet Akışı Çözüm Yolu
- Konuşma geçmişini veya sayfalandırma imlecini görüntülemek için oturuma ait mevcut mesajları getirin (
GET /ai/sessions/:sessionId/messages). - Yeni bir kullanıcı mesajı gönderin ('POST /ai/sessions/:sessionId/messages') ve hem 'userMessage'ı hem de 'assistantMessage.runId'yi yakalayın.
- Asistan çıktısını
GET /ai/sessions/:sessionId/messages/:messageId/stream(veya çalıştırma akışı) yoluyla aktarın ve `message.delta' olaylarını geldiklerinde kullanıcı arayüzüne ekleyin. - Kullanıcı asistanın sözünü keserse, kısmi içeriği sonlandırmak ve "durum: durduruldu"yu göstermek için "POST /ai/sessions/:sessionId/messages/:assistantMessageId/stop" öğesini çağırın.
const startChat = async (sessionId) => {
const history = await fetch(
`${BASE_URL}/ai/sessions/${sessionId}/messages`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
console.log("Existing messages:", (await history.json()).data);
const reply = await fetch(
`${BASE_URL}/ai/sessions/${sessionId}/messages`,
{
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ content: "Show me a recap of today's tasks." }),
}
);
const {
assistantMessage: { id: assistantId },
} = (await reply.json()).data;
const stream = new EventSource(
`${BASE_URL}/ai/sessions/${sessionId}/messages/${assistantId}/stream`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
stream.addEventListener("message.delta", (event) => {
const { payload } = JSON.parse(event.data);
console.log("Delta:", payload.delta);
});
};Uç noktalar
| Method | Path | Description | Auth | Rate Limit |
|---|---|---|---|---|
| GET | /ai/sessions/:sessionId/messages | List messages | JWT + Entitlement | 60/min |
| POST | /ai/sessions/:sessionId/messages | Send a message | JWT + Entitlement | 20/min |
| GET | /ai/sessions/:sessionId/messages/:messageId/stream | SSE message stream | JWT + Entitlement | 20/min |
| POST | /ai/sessions/:sessionId/messages/:assistantMessageId/stop | Stop generation | JWT + Entitlement | 30/min |
GET /ai/sessions/:sessionId/messages
Tanım
İmleç tabanlı veya sayfa tabanlı sayfalandırmayla bir oturumdaki mesajları listeleyin.
Kimlik Doğrulama: JWT Taşıyıcı jetonu + aktif AI yetkisi gereklidir. Hız sınırı: 60/dak
Rica etmek
- Başlıklar:
Authorization: Bearer <token> - Yol parametreleri:
sessionId
Sorgu Parametreleri
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | No | Number of messages to return |
cursor | string | No | Cursor for cursor-based pagination |
offset | number | No | Offset for page-based pagination |
chainyId | string | No | Filter by Chainy. Returns 404 if the session is not associated with this Chainy. |
Cevap
Yanıt Örneği
{
"data": [
{
"id": "cm5msg001",
"role": "user",
"content": "How can I improve my vocabulary retention rate?",
"createdAt": "2026-03-17T10:05:00.000Z"
},
{
"id": "cm5msg002",
"role": "assistant",
"content": "Spaced repetition is one of the most effective techniques...",
"status": "completed",
"toolCalls": [
{
"id": "tc_abc123",
"toolKey": "memory.search",
"input": { "query": "vocabulary retention" },
"status": "completed",
"output": { "total": 2 },
"error": null,
"executionMs": 64
}
],
"suggestions": [
{
"suggestion": "Can you turn that into a 7-day vocabulary routine?",
"priority": 1
},
{
"suggestion": "What should I do when I keep forgetting the same words?",
"priority": 2
}
],
"tokensUsed": 850,
"createdAt": "2026-03-17T10:05:00.000Z"
}
],
"meta": {
"cursor": "eyJpZCI6ImNtNW1zZzAwMiJ9",
"hasMore": false,
"total": 2
}
}Yanıt Alanları
| Field | Type | Description |
|---|---|---|
id | string | Message ID |
role | string | user or assistant |
content | string | null | Message content |
status | string | Assistant messages: running, completed, stopped, failed |
suggestions | object[] | Follow-up suggestion cards returned separately from the assistant markdown. Empty when disabled, unavailable, or not generated. |
runId | string | null | ID of the AI run that produced this message. Use this to attach a stream listener on page reload. Present on all assistant messages once the run is created. |
toolCalls | object[] | null | For Chao sessions: list of tool calls made during this message. See Tool Call Fields below. |
modelId | string | null | ID of the model that generated the response |
modelName | string | null | Display name of the model |
providerKey | string | null | Provider identifier (e.g. "anthropic", "openai") |
createdAt | string | ISO 8601 |
Takım Çağrı Alanları
'toolCalls'daki her giriş, bu mesaj sırasında Chao tarafından çağrılan bir aracı temsil eder:
| Field | Type | Description |
|---|---|---|
id | string | Tool call ID (matches SSE callId, toolCallId, or stepId) |
toolKey | string | Tool name (e.g. "bits.create", "chainies.list") |
input | object | Arguments Chao passed to the tool |
status | string | pending, executing, completed, failed, degraded, rejected, or skipped |
output | object | null | Tool result (present when status is completed) |
error | string | null | Error message (present when status is failed) |
executionMs | number | null | Execution duration in milliseconds |
'toolCalls' kalıcıdır ve her geçmiş isteğinde döndürülür. Sayfa yeniden yüklendiğinde, bu alandan araç kartlarını yeniden oluşturun ve yardımcı mesajın hala etkin bir "runId"si varsa bir akış dinleyicisini yeniden ekleyin.
Canlı SSE yüklerini aynı kart şekline göre normalleştirin:
| Normalized field | Preferred lookup |
|---|---|
toolKey | payload.toolKey ?? payload.key |
callId | payload.callId ?? payload.toolCallId ?? envelope.stepId |
input | payload.input ?? payload.args |
output | payload.data ?? payload.output |
'payload.activity' mevcut olduğunda, bu nesneden kart başlığını, ayrıntısını, durumunu ve konusunu işleyin.
Kod Örnekleri
Oturum Oluştur'ın yanıtındaki ("data.id") "id"yi "$SESSION_ID" olarak kullanın. Zincirli filtre için, Create Chainy öğesindeki "kimliği" "$CHAINY_ID" olarak kullanın.
curl "https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/messages?limit=20" \
-H "Authorization: Bearer $TOKEN"
# Filter by Chainy:
curl "https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/messages?limit=20&chainyId=$CHAINY_ID" \
-H "Authorization: Bearer $TOKEN"const sessionId = process.env.SESSION_ID; // id from Create a Session's response
const params = new URLSearchParams({ limit: "20" });
const res = await fetch(
`${BASE_URL}/ai/sessions/${sessionId}/messages?${params}`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { data, meta } = await res.json();
// Filter by Chainy:
const chainyId = process.env.CHAINY_ID; // id of an existing Chainy (see Create Chainy)
const chainyParams = new URLSearchParams({
limit: "20",
chainyId,
});
const chainyRes = await fetch(
`${BASE_URL}/ai/sessions/${sessionId}/messages?${chainyParams}`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);import os
import requests
session_id = os.environ["SESSION_ID"] # id from Create a Session's response
res = requests.get(
f"{BASE_URL}/ai/sessions/{session_id}/messages",
headers={"Authorization": f"Bearer {TOKEN}"},
params={"limit": 20},
)
body = res.json()
# Filter by Chainy:
chainy_id = os.environ["CHAINY_ID"] # id of an existing Chainy (see Create Chainy)
chainy_res = requests.get(
f"{BASE_URL}/ai/sessions/{session_id}/messages",
headers={"Authorization": f"Bearer {TOKEN}"},
params={
"limit": 20,
"chainyId": chainy_id,
},
)POST /ai/sessions/:sessionId/messages
Tanım
Asistan yanıtını oluşturmak için bir yapay zeka çalışmasını tetikleyen bir oturuma kullanıcı mesajı gönderin.
Kimlik Doğrulama: JWT Taşıyıcı jetonu + aktif AI yetkisi gereklidir. Hız sınırı: 20/dak
Rica etmek
- Başlıklar:
Authorization: Bearer <token>,Content-Type: application/json - Yol parametreleri:
sessionId
Talep Gövdesi
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
content | string | Yes | Non-empty, ≤ 20,000 characters | Message content. The 20,000-character cap applies to every caller, including the seed message returned by feature endpoints such as POST /productivity/priority-analysis/runs. |
model | string | No | Active model key | Override the model for this message |
effortMode | string | No | "basic", "thinking", or "pro" | High-level model tier preference. basic uses a standard model, thinking selects a thinking-capable model, pro selects the highest-capability tier. Overrides the session-level effortMode if both are set. Exact model selection remains a backend hint. |
provider | string | No | Lowercase identifier (e.g. openai) | AI provider key. Requires a paid plan with the corresponding provider entitlement. |
capabilityKey | string | No | ai.search.web, ai.research.deep, ai.image.generate, ai.video.generate, ai.audio.generate | Explicit Chao capability to execute deterministically. When set, the matching capability-specific parameters are accepted (see Capability Parameters). |
attachmentIds | string[] | No | Valid file IDs | Array of file IDs to attach |
memoryIds | string[] | No | Valid memory IDs | Optional memory items to pin into the run |
idempotencyKey | string | No | — | Client-side dedupe key for retries |
parameters | object | No | Capability-specific params | Long-term contract for capability-specific parameters. See Capability Parameters. |
structuredBlocks | object[] | No | Mention/media blocks | Structured user-side blocks such as agent mentions or media references |
Yeteneğe özgü alanlar ("durationSeconds", "aspectRatio", "generateAudio" vb. gibi) da geriye dönük uyumluluk için üst düzeyde gönderilebilir. Aşağıdaki bölüme bakın.
Yetenek Parametreleri
'capabilityKey' ayarlandığında mesaj uç noktası, yeteneğin bildirdiği parametreleri kabul eder. İki eşdeğer istek şekli desteklenir:
- Üst düzey alanlar (mevcut istemci uyumluluğu):json
{ "content": "lo-fi beat with a deep bass line", "capabilityKey": "ai.audio.generate", "durationSeconds": 20, "bpm": 90, "styleTokens": ["lo-fi", "chill"] } - İç içe geçmiş 'parametreler' nesnesi (uzun vadeli sözleşme, yeni kod için önerilir):json
{ "content": "lo-fi beat with a deep bass line", "capabilityKey": "ai.audio.generate", "parameters": { "durationSeconds": 20, "bpm": 90, "styleTokens": ["lo-fi", "chill"] } }
Her iki form da mevcut olduğunda, çarpışma durumunda iç içe değerler kazanır.
Yetenek başına kabul edilen parametreler:
| capabilityKey | Accepted parameters |
|---|---|
ai.audio.generate | durationSeconds (5–30), bpm (40–220), styleTokens (string[], ≤16 items, ≤64 chars each). See Audio Generation. |
ai.image.generate | aspectRatio (W:H), quality (standard|hd|auto), numImages / numberOfImages (alias for count, 1–4), seed, negativePrompt (≤4000 chars), size (1024x1024|1792x1024|1024x1792), style (vivid|natural), resolution, provider, model, activeImageId. See Generative Media. |
ai.video.generate | aspectRatio (16:9|9:16|1:1|4:3|3:4|21:9), duration (1–60, accepts numeric strings), resolution (480p|720p|1080p|4k), size (WxH), generateAudio, negativePrompt, seed, styleTokens, inputImageUrl, inputVideoUrl, referenceImages[], referenceVideos[], provider (kling|veo|sora), model. See Video Generation. |
ai.search.web | maxResults (1–20) |
ai.research.deep | depth (standard|deep) |
Seçilenden farklı bir yeteneğe ait olan yetenek alanları kesin bir hatayla reddedilir ("bpm yalnızca ai.audio.generate için geçerlidir"). Gerçekten bilinmeyen alanlar da 'bilinmeyen X özelliği' ile reddedilir. Sade sohbet ("capabilityKey" yok) orijinal DTO sözleşmesini korur; ekstra alanlar hâlâ reddedilir.
Cevap
Yanıt Örneği
{
"data": {
"sessionId": "$SESSION_ID",
"userMessage": {
"id": "cm5msg001",
"role": "user",
"content": "How can I improve my vocabulary retention rate? I keep forgetting words after a few days.",
"createdAt": "2026-03-17T10:05:00.000Z"
},
"assistantMessage": {
"id": "cm5msg002",
"role": "assistant",
"content": "",
"suggestions": [],
"createdAt": "2026-03-17T10:05:00.000Z"
},
"run": {
"id": "cm5run003",
"status": "queued"
}
}
}Asistan mesaj kabuğu, "öneriler: []" ile hemen döndürülür. Öneriler, asistan yanıtını yazan aynı model çağrı tarafından üretilir ve geçmiş okumaları ve "message.suggestions" SSE olayı aracılığıyla "message.completed" ile aynı onay işaretinde iletilir.
Yanıt Alanları
| Field | Type | Description |
|---|---|---|
userMessage.id | string | User message ID |
userMessage.role | string | Always user |
userMessage.content | string | Message content |
userMessage.createdAt | string | ISO 8601 |
assistantMessage.id | string | Assistant message ID |
assistantMessage.role | string | Always assistant |
assistantMessage.content | string | Empty string while generating |
assistantMessage.suggestions | object[] | Always [] in the immediate POST response shell |
run.id | string | Associated AI run ID |
run.status | string | Initial run status, usually queued |
Hata Örneği
{
"error": {
"code": "bad_request",
"message": "bpm is only valid for ai.audio.generate; unknown property foo",
"details": {
"fields": [
{ "field": "bpm", "message": "bpm is only valid for ai.audio.generate", "capabilityKey": "ai.audio.generate" },
{ "field": "foo", "message": "unknown property foo" }
]
}
},
"meta": { "requestId": "<request-id>" }
}Kod Örnekleri
Oturum Oluştur'ın yanıtındaki ("data.id") "id"yi "$SESSION_ID" olarak kullanın.
curl -X POST https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/messages \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "How can I improve my vocabulary retention rate? I keep forgetting words after a few days."
}'const sessionId = process.env.SESSION_ID; // id from Create a Session's response
const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}/messages`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content:
"How can I improve my vocabulary retention rate? I keep forgetting words after a few days.",
}),
});
const { data } = await res.json();import os
import requests
session_id = os.environ["SESSION_ID"] # id from Create a Session's response
res = requests.post(
f"{BASE_URL}/ai/sessions/{session_id}/messages",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={
"content": "How can I improve my vocabulary retention rate? I keep forgetting words after a few days."
},
)
data = res.json()["data"]GET /ai/sessions/:sessionId/messages/:messageId/stream
Tanım
Yardımcı mesaj oluşturulurken artımlı içerik almak için Sunucu Tarafından Gönderilen Olaylar akışına bağlanın.
Kimlik Doğrulama: JWT Taşıyıcı jetonu + aktif AI yetkisi gereklidir. Hız sınırı: 20/dak
Rica etmek
- Başlıklar:
Authorization: Bearer <token>,Accept: text/event-stream - Yol parametreleri:
sessionId,messageId
Cevap
Yanıt Örneği
event: message.delta
data: {"eventId":1,"type":"message.delta","runId":"cm5run003","payload":{"delta":"Spaced repetition is one of the most "}}
event: message.delta
data: {"eventId":2,"type":"message.delta","runId":"cm5run003","payload":{"delta":"effective techniques for long-term retention. "}}
event: message.delta
data: {"eventId":3,"type":"message.delta","runId":"cm5run003","payload":{"delta":"Here are some strategies tailored to your chain..."}}
event: message.completed
data: {"eventId":4,"type":"message.completed","runId":"cm5run003","payload":{"messageId":"cm5msg002","content":"Spaced repetition is one of the most effective techniques for long-term retention. Here are some strategies tailored to your chain..."}}Yanıt Alanları
| Field | Type | Description |
|---|---|---|
event | string | SSE event type such as message.delta, message.completed, tool.started, tool.completed, run.error |
data.payload.delta | string | Incremental content token(s) for message.delta |
data.payload.content | string | Full assistant content for message.completed |
data.payload.messageId | string | Assistant message ID when present |
Kod Örnekleri
Create a Session'ın yanıtındaki (data.id) '$SESSION_ID'yi kullanın ve Send a message'ın yanıtındaki (data.assistantMessage.id) 'id'yi '$MESSAGE_ID' olarak kullanın.
curl -N "https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/messages/$MESSAGE_ID/stream" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: text/event-stream"// Browser — uses built-in EventSource (no auth header support)
// For Node.js, install: npm install eventsource
import EventSource from 'eventsource';
const sessionId = process.env.SESSION_ID; // id from Create a Session's response
const messageId = process.env.MESSAGE_ID; // assistantMessage.id from Send a Message's response
const es = new EventSource(
`${BASE_URL}/ai/sessions/${sessionId}/messages/${messageId}/stream`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
es.addEventListener('message.delta', (e) => {
const { payload } = JSON.parse(e.data);
process.stdout.write(payload.delta);
});
es.addEventListener('message.completed', () => es.close());
es.addEventListener('run.error', (e) => {
const { payload } = JSON.parse(e.data);
console.error('Run error:', payload.error);
es.close();
});import os
import sseclient
import requests
session_id = os.environ["SESSION_ID"] # id from Create a Session's response
message_id = os.environ["MESSAGE_ID"] # assistantMessage.id from Send a Message's response
response = requests.get(
f"{BASE_URL}/ai/sessions/{session_id}/messages/{message_id}/stream",
headers={
"Authorization": f"Bearer {TOKEN}",
"Accept": "text/event-stream",
},
stream=True,
)
client = sseclient.SSEClient(response)
for event in client.events():
if event.event == "message.delta":
print(event.data, end="", flush=True)
elif event.event == "message.completed":
breakPOST /ai/sessions/:sessionId/messages/:assistantMessageId/stop
Tanım
Devam eden bir asistan mesajı oluşturma işlemini durdurun.
Kimlik Doğrulama: JWT Taşıyıcı jetonu + aktif AI yetkisi gereklidir. Hız sınırı: 30/dak
Rica etmek
- Başlıklar:
Authorization: Bearer <token> - Yol parametreleri:
sessionId,assistantMessageId
Cevap
Yanıt Örneği
{
"data": {
"id": "cm5msg002",
"status": "stopped",
"content": "Spaced repetition is one of the most effective techniques for long-term retention. ",
"stoppedAt": "2026-03-17T10:05:05.000Z"
}
}Yanıt Alanları
| Field | Type | Description |
|---|---|---|
id | string | Message ID |
status | string | Always stopped |
content | string | Partial content generated before stopping |
stoppedAt | string | ISO 8601 timestamp of stop |
Kod Örnekleri
Create a Session'ın yanıtındaki (data.id) '$SESSION_ID'yi kullanın ve Send a message'ın yanıtındaki (data.assistantMessage.id) 'id'yi şu şekilde kullanın: "$ASSISTANT_MESSAGE_ID".
curl -X POST https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/messages/$ASSISTANT_MESSAGE_ID/stop \
-H "Authorization: Bearer $TOKEN"const sessionId = process.env.SESSION_ID; // id from Create a Session's response
const assistantMessageId = process.env.ASSISTANT_MESSAGE_ID; // assistantMessage.id from Send a Message's response
const res = await fetch(
`${BASE_URL}/ai/sessions/${sessionId}/messages/${assistantMessageId}/stop`,
{
method: "POST",
headers: { Authorization: `Bearer ${TOKEN}` },
}
);
const { data } = await res.json();import os
import requests
session_id = os.environ["SESSION_ID"] # id from Create a Session's response
assistant_message_id = os.environ["ASSISTANT_MESSAGE_ID"] # assistantMessage.id from Send a Message's response
res = requests.post(
f"{BASE_URL}/ai/sessions/{session_id}/messages/{assistant_message_id}/stop",
headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]