Skip to main content

Response Synthesis

Response synthesis turns plan and runner output into the final assistant-facing answer. It should summarize what happened without hiding stage, failed step, or reason-code evidence.

The helpers use an OntologyLLM interface. The adapter decides which provider and model to use.

Output Contract

Response synthesis is deliberately the last mile. It should never be the only place where execution state is preserved.

InputKept ForNotes
requirementuser-facing contextuse the original request, not a rewritten guess
resultsuccess summaryproject or compress large payloads first
failed_stepfailure localizationprefer stable step ids when available
error.reason_codeproduct diagnosticskeep the structured code alongside the final answer
partial_resultsuseful progressinclude only scrubbed, non-sensitive summaries

Public Helpers

from graph_tool_call.plan import (
synthesize_failure_response,
synthesize_success_response,
)

Success Response

answer = synthesize_success_response(
requirement="회원 배송지를 조회해줘",
result=trace.output,
llm=llm,
result_char_limit=4000,
)

The success prompt is careful about counts. If the API result is truncated and does not contain an explicit total field, the model should not claim an absolute total.

Failure Response

answer = synthesize_failure_response(
requirement="회원 배송지를 조회해줘",
failed_step=trace.failed_step or "unknown",
error={"reason_code": "auth_failed", "message": "HTTP 403"},
partial_results=[step.output for step in trace.steps if step.error is None],
llm=llm,
)

Failure responses should explain:

  • what the user asked for
  • what was attempted
  • where it failed
  • the plain-language reason
  • what can be tried next, if obvious

Adapter Guidance

Before calling response synthesis:

  • project or compress large API payloads
  • scrub sensitive values
  • preserve plan_id, failed_step, and reason code
  • keep raw audit payloads outside the engine
  • pass the same trace metadata to logs/SSE so the final answer can be audited

Deterministic Fallback

Use a template instead of LLM synthesis when the answer must be strict JSON, when compliance requires approved language, or when the failure reason is already actionable. A common adapter pattern is:

if response_format == "json" or error.reason_code in {"auth_failed", "auth_context_required"}:
return deterministic_response(trace)

return synthesize_failure_response(..., llm=llm)

The key rule is that synthesis can make the answer easier to read, but it should not invent missing totals, hide failed stages, or rewrite a structured reason into a vague apology.

Quality Checks

For real integrations, verify that success and failure answers preserve:

  • the selected target tool
  • plan_id and failed step, when present
  • the reason code for structured failures
  • truncation limits for large payloads
  • absence of raw tokens, cookies, phone numbers, or internal ids

When Not To Use It

Skip response synthesis when the product already has a strict response format, when the result must be machine-readable JSON, or when compliance policy requires a deterministic template.