SDK tutorial · 7 of 10
Consume turn results
Render and automate from structured result fields. Do not parse assistant prose or raw provider errors to decide retry, billing, or credential behavior.
Customization depth
Level 3 · Structured result handling
Hosting depth
Any conversation-engine host
Documentation status
Supported SDK boundary
Assumptions
- The product needs deterministic behavior after a turn settles.
- Provider diagnostics must not cross the public API boundary unchanged.
- Product-specific response schemas will be projected from Heddle's host-facing result.
- Return the persisted summary, safe failure category, updated session, trace path, session artifacts, and current-turn tool results.
- Normalize model failures without credentials or raw provider messages.
- Distinguish quota exhaustion from retryable rate limiting.
- Map Heddle outcomes and failure codes into product API errors, UI state, metrics, and retry policy.
- Project only intended public fields across a transport boundary.
- Keep trace files and internal tool payloads behind product authorization.
Read the host-facing result
const result = await engine.turns.submit({
sessionId,
prompt,
host,
})
console.log(result.outcome)
console.log(result.summary)
console.log(result.failure)
console.log(result.session.id)
console.log(result.traceFile)
console.log(result.artifacts.map((artifact) => artifact.id))
console.log(result.toolResults.map((entry) => entry.call.tool))The fields have distinct responsibilities:
| Field | Use it for |
|---|---|
outcome | Why runtime execution stopped. |
summary | The persisted assistant summary for the turn. |
failure | Stable, safe model-failure classification. |
session | The updated persisted conversation record. |
traceFile | Optional local path to lower-level evidence. |
artifacts | Artifacts currently associated with the session. |
toolResults | Completed calls from this turn, including input, result, duration, step, and timestamp. |
Branch on failure codes, never prose
switch (result.failure?.code) {
case 'authentication':
throw new ProductModelCredentialError()
case 'quota':
throw new ProductModelQuotaError()
case 'rate_limit':
scheduleBoundedRetry()
break
}Current model failure codes are:
authentication— rejected or missing usable credentials;permission— credential exists but cannot perform the request;quota— billing/quota capacity is exhausted and is non-retryable without an external change;rate_limit— transient throttling that may be retried with product policy;request— invalid or unsupported provider request;transport— network or provider transport failure;empty_response— the model returned no usable response;unknown— no safer stable classification was available.
failure never contains credentials or raw provider messages. Do not inspect summary for error strings; it is user-facing assistant content and can change independently.
Project a public result
When the turn crosses an API boundary, create an explicit product schema:
const publicResult = {
outcome: result.outcome,
message: result.summary,
failureCode: result.failure?.code,
artifacts: result.artifacts.map(({ id, kind, title }) => ({
id,
kind,
title,
})),
}Do not send traceFile, unrestricted tool inputs/results, storage paths, or provider diagnostics to an untrusted client by default.
Use traces only for deeper evidence
Most product behavior should use turn-result fields and semantic activity. Reach for the raw trace when an authorized operator needs audit evidence, debugging, or custom analysis.