feat(x_search): add structured output and response chaining#27416
feat(x_search): add structured output and response chaining#27416valda wants to merge 2 commits into
Conversation
67bcca7 to
3f72b51
Compare
3f72b51 to
a166a06
Compare
Extend the built-in x_search tool with four parameters that expose additional capabilities of the xAI Responses API: - output_schema: expanded to text.format.json_schema (strict=true) - instructions: top-level system instructions for response style - previous_response_id: continue from a prior call's response - store: whether xAI retains the response (default false) Auto-enable store when previous_response_id is provided so chains work without callers tracking both flags. instructions and previous_response_id are mutually exclusive per the xAI Responses API — when both are set, instructions is dropped with a warning log rather than raising, to avoid raise-and-retry loops in upstream LLM callers. The success payload gains response_id (from data["id"]) and structured_output (parsed JSON when output_schema is set, None otherwise). Existing fields (answer, citations, inline_citations, credential_source, etc.) are preserved unchanged, and failure payloads keep their current shape. Authentication, retry, structured errors, and citation extraction are unchanged; only the request shape and response parsing are extended.
Add 11 unit tests for the new parameters: - output_schema expands to text.format.json_schema (strict=true) - instructions lands at the top level of the request body - previous_response_id lands at the top level and auto-enables store - instructions is dropped when previous_response_id is also set - store defaults to False; explicit store=True is honored - response_id surfaces from data["id"] on success - structured_output is None without a schema - structured_output is None on JSON parse failure (success stays True) - non-object output_schema returns a tool_error - whitespace-only instructions / previous_response_id are omitted The 13 existing tests are unchanged and still pass.
a166a06 to
5103c42
Compare
|
Thanks for the focused x_search enhancement. I reviewed the diff against the current checkout and did not find a concrete blocking issue from static inspection. Current main still lacks the requested surface: tools/x_search_tool.py:274 defines x_search_tool without output_schema, instructions, previous_response_id, or store; tools/x_search_tool.py:325 hard-codes "store": False; and tools/x_search_tool.py:455 exposes none of those fields in X_SEARCH_SCHEMA. The PR diff adds request construction, success-payload parsing, and tests for those paths. Staleness looks mechanical: I did not run pytest or live xAI calls because this sweeper pass is read-only, so this is a static review only. Automated hermes-sweeper review. |
|
Thanks for the review. I use this feature daily in my own Hermes workflow, especially structured output and response chaining for x_search-based reporting, so it would be very helpful if this could be merged or salvaged into main. I’m happy to rebase/update the PR and run the relevant tests if that would help. |
Summary
Extend the built-in
x_searchtool with four parameters that expose additional xAI Responses API capabilities:output_schema— strict JSON Schema output, expanded intotext.format.json_schema.instructions— top-level system-style instructions controlling response style.previous_response_id— chain a follow-up call from a stored prior response.store— whether xAI stores the response so itsidcan be reused later. Defaults tofalse.The success payload now includes:
response_id— the xAI responseid, for follow-up chaining.structured_output— parsed JSON whenoutput_schemais set and parsing succeeds, otherwisenull.Existing fields, error shape, credential resolution, retry behavior, and citation extraction are unchanged.
Why this matters for agent loops
x_searchalready returns an LLM-summarized answer with citations. But agent workflows often need typed fields — extracted items, classification labels, confidence annotations, or alert decisions — that downstream steps can consume without sending the prose through another LLM pass to recover the shape.With
output_schema, a singlex_searchcall can return a strictly-shaped JSON object directly. The schema becomes an explicit tool contract rather than an implicit prompt convention, which matters most for skills and cron jobs that run the same query repeatedly: they can declare the expected shape once and rely on it across invocations, instead of re-coaxing it out of free-form text each time.Combined with
previous_response_id, follow-up calls can refine the same search while keeping the structured shape stable across turns.This is additive: callers that do not pass
output_schemakeep the existing conversational response shape.Scope
This PR intentionally bundles the four new parameters together because they share the same tool schema, request payload construction, response parsing, and tests. Splitting them would create overlapping changes in
tools/x_search_tool.pywithout making review materially easier.Out of scope:
warningsfield to tool responses.Behavior
store=falseremains the default to preserve current privacy semantics.store=trueon the initial/seed call when they plan to reuse itsresponse_idwithprevious_response_id.previous_response_idis provided, the request is stored automatically so chained follow-up responses can themselves be reused.instructionsandprevious_response_idare mutually exclusive per the xAI Responses API. If both are provided,instructionsis ignored and a warning is logged.previous_response_idwins because it is required to preserve the requested response chain.response_idis only included on the success path. Failure responses keep the existing error shape.structured_outputis always present on the success path:nullwhenoutput_schemais not provided.output_schemais provided and parsing succeeds.nullwhen parsing fails, while preserving the rawanswerand keeping the tool call successful.Testing
output_schemaexpands intotext.format.json_schema.instructionsis added as a top-level field.previous_response_idis added as a top-level field.instructionsis dropped whenprevious_response_idis also provided.storedefaults tofalse.store=trueis honored.previous_response_idautomatically enablesstore.data.idis returned asresponse_idon success.structured_output.structured_outputasnullwithout failing the tool call.output_schemamust be a JSON object.instructionsandprevious_response_idvalues are omitted from the request body.Dogfood
Verified against the live xAI Responses API:
Output (handles anonymized):
This single round-trip confirms:
response_idis a non-null UUID — provesstore=Truetook effect on the seed call.structured_outputis a parseddictmatching the declared schema.success=trueand references the prior turn's posts by handle — proves the response was actually re-used by the API, not just acknowledged.inline_citationsis populated even when top-levelcitationsis empty.