Search

Search HiAPI models, tools, and resources.

Back to blog
Guide

gpt-6.1-sol Prompt Recipes: Coding, Reasoning, JSON and Tool Calls With Real Outputs

hiapigpt-6.1-solpromptsreasoning

gpt-6.1-sol is a reasoning-grade text model on hiapi — chat, coding, and step-by-step reasoning, served over the Responses API (POST /v1/responses). If you already know how to call it, this page is the next step: a set of copy-paste prompt recipes for the four jobs people actually reach for it — coding, reasoning, strict JSON, and tool calls — each shown with the exact output it returned when we ran it for this article. For auth, streaming, and SSE parsing, start with the setup guide; here we focus only on the prompts.

Every recipe below is a request body you drop into that setup. Two fields carry the prompt: top-level instructions (persona and formatting rules) and the input array (the task itself). Nothing here is theoretical — the outputs are pasted verbatim from real response.completed events.

Three levers that change how you prompt gpt-6.1-sol

Before the recipes, three things about this model shape every prompt you write. All three are confirmed against the live model contract on hiapi.

  1. There is no temperature and no top_p. This execution profile disables both (and max_output_tokens). You cannot dial determinism or creativity through sampling — the only knobs are your instructions, your input, and reasoning.effort. If you want terse, deterministic-feeling output, you say so in instructions; you can't set temperature: 0.
  2. reasoning.effort has five levels: low, medium, high, xhigh, max (default medium). Higher effort spends more hidden reasoning tokens — and those bill as output tokens. Recipe 2 shows the real curve.
  3. The context window is ~1.05M tokens (max output 128K). Per-token pricing is tiered: once a single request's input crosses 272K tokens, the input/output rate roughly doubles. For everyday prompts you're nowhere near that line; for long-context jobs (Recipe 5) it's worth knowing.

Recipe 1 — Coding: generate a function to spec

Put the engineering persona and the output shape in instructions, and the spec in input. Constraining the shape ("one fenced block, then one sentence") is how you stop a reasoning model from wrapping code in three paragraphs of preamble.

{
  "model": "gpt-6.1-sol",
  "instructions": "You are a senior Python engineer. Return a single fenced Python code block, then one sentence on complexity. No preamble.",
  "input": [
    { "type": "message", "role": "user", "content": [
      { "type": "input_text", "text": "Write `merge_intervals(intervals: list[list[int]]) -> list[list[int]]` that merges overlapping closed intervals and returns them sorted by start. Handle the empty list. Include a docstring." }
    ] }
  ],
  "reasoning": { "effort": "low" },
  "stream": true
}

What it returned (verbatim):

def merge_intervals(intervals: list[list[int]]) -> list[list[int]]:
    """Merge overlapping closed intervals, returning them sorted by start.

    The input list and its intervals are not modified.
    """
    if not intervals:
        return []

    ordered = sorted(intervals, key=lambda interval: interval[0])
    merged = [ordered[0].copy()]

    for start, end in ordered[1:]:
        if start <= merged[-1][1]:
            merged[-1][1] = max(merged[-1][1], end)
        else:
            merged.append([start, end])

    return merged

Time complexity is O(n log n), and space complexity is O(n).

Note what the constraint bought: it respected the empty-list case, copied each interval before mutating (ordered[0].copy()) so the caller's data is untouched, and stopped at exactly one sentence of analysis. For mechanical coding like this, effort: low is enough — it used zero reasoning tokens and still produced correct, non-mutating code.

Recipe 2 — Reasoning: control the thinking budget with effort

Because you can't set temperature, reasoning.effort is your main dial for hard problems. Keep the prompt identical and only change effort:

{
  "model": "gpt-6.1-sol",
  "instructions": "Think step by step, then end with a line `Answer: <value>`.",
  "input": [
    { "type": "message", "role": "user", "content": [
      { "type": "input_text", "text": "A bakery sells cookies in boxes of 6 and 11. What is the largest number of cookies that CANNOT be bought exactly? Show the reasoning." }
    ] }
  ],
  "reasoning": { "effort": "medium" },
  "stream": true
}

We ran the same prompt at all five effort levels. Every level returned the correct answer, 49. What changed was how much thinking it bought:

reasoning.effortreasoning tokenstotal output tokensapprox. cost*
low76305≈ $0.0008
medium121380≈ $0.0010
high209427≈ $0.0011
xhigh626845≈ $0.0021
max622813≈ $0.0021

<small>*At base-tier rates ($0.50 / 1M input, $2.50 / 1M output); reasoning tokens bill as output. Figures from this run, as of 2026-10. Check the pricing page for current rates.</small>

The practical lesson is in the last two rows: effort climbs cleanly from low to high, then plateaus — xhigh and max both land around 620 reasoning tokens because the problem simply isn't hard enough to need more. Maxing out an easy prompt doesn't buy a better answer; it buys ~2.5× the output tokens for the same "49." Match effort to difficulty: low/medium for most prompts, high and up only when the task genuinely needs deeper search.

Here is the medium output, so you can see the shape the prompt produced:

The largest number is 49 cookies.

1. Show that 49 cannot be bought exactly. Suppose 49 = 6a + 11b, where a, b are nonnegative integers. Taking both sides modulo 6 gives 5b ≡ 1 (mod 6), so b ≡ 5 (mod 6). Thus b must be at least 5, but five boxes of 11 already contain 55 cookies. This is impossible.

2. Show that every number above 49 can be bought. … Every integer at least 50 is one of six consecutive reachable totals plus a nonnegative multiple of 6.

Answer: 49

The Answer: <value> line in instructions is doing real work: it gives you a trivial last-line parse (text.rsplit("Answer:", 1)[-1].strip()) without forcing the model to drop its reasoning.

Recipe 3 — Strict JSON with a schema

Don't ask for JSON in prose and hope. gpt-6.1-sol supports strict structured output: pass text.format with a json_schema, and the model is constrained to emit conforming JSON — no fences, no stray prose.

{
  "model": "gpt-6.1-sol",
  "instructions": "Classify the support ticket. Respond only with the JSON object.",
  "input": [
    { "type": "message", "role": "user", "content": [
      { "type": "input_text", "text": "Ticket: 'The 4K upscale endpoint returns a 500 every time since this morning. We have a launch tomorrow and this is blocking us.'" }
    ] }
  ],
  "text": {
    "format": {
      "type": "json_schema",
      "name": "ticket",
      "strict": true,
      "schema": {
        "type": "object",
        "properties": {
          "sentiment": { "type": "string", "enum": ["positive", "neutral", "negative"] },
          "topics": { "type": "array", "items": { "type": "string" } },
          "action_required": { "type": "boolean" }
        },
        "required": ["sentiment", "topics", "action_required"],
        "additionalProperties": false
      }
    }
  },
  "reasoning": { "effort": "low" },
  "stream": true
}

What it returned (verbatim, a single line):

{"action_required":true,"sentiment":"negative","topics":["4K upscale endpoint","HTTP 500 errors","Service outage","Launch blocker","Urgent support"]}

Two things to internalize. First, strict: true guarantees the types and required keys, but not key order — note action_required came out first even though the schema lists it last, so parse by key, never by position. Second, you still accumulate the answer from response.output_text.delta chunks like any other response; the schema shapes the content, not the transport.

Recipe 4 — Tool calling and result continuation

gpt-6.1-sol can call functions and — importantly — continue after you return a result. Declare a tools array; when the model decides to call, it emits a function_call item instead of text.

{
  "model": "gpt-6.1-sol",
  "instructions": "You can call tools. When the user asks about a task, call get_task_status.",
  "input": [
    { "type": "message", "role": "user", "content": [
      { "type": "input_text", "text": "Can you check what's going on with task_abc123? It's been pending for ages." }
    ] }
  ],
  "tools": [
    {
      "type": "function",
      "name": "get_task_status",
      "description": "Look up the status of an async image/video generation task by its id.",
      "parameters": {
        "type": "object",
        "properties": { "task_id": { "type": "string", "description": "The task id, e.g. 'task_abc123'." } },
        "required": ["task_id"],
        "additionalProperties": false
      }
    }
  ],
  "reasoning": { "effort": "low" },
  "stream": true
}

The response carried no text — just a tool call, delivered as a function_call item in the final event (its arguments stream in as response.function_call_arguments.delta chunks):

{
  "type": "function_call",
  "call_id": "call_e4a8a52c6db04cafb6a744f3727c456b",
  "name": "get_task_status",
  "arguments": "{\"task_id\":\"task_abc123\"}"
}

Now the second half, which the basic setup doesn't cover: run your function, then hand the result back by appending the model's function_call and your function_call_output (keyed by the same call_id) to the input array and calling again:

{
  "model": "gpt-6.1-sol",
  "instructions": "You can call tools. Summarize tool results for the user in one or two sentences.",
  "input": [
    { "type": "message", "role": "user", "content": [ { "type": "input_text", "text": "Can you check what's going on with task_abc123? It's been pending for ages." } ] },
    { "type": "function_call", "call_id": "call_e4a8a52c6db04cafb6a744f3727c456b", "name": "get_task_status", "arguments": "{\"task_id\":\"task_abc123\"}" },
    { "type": "function_call_output", "call_id": "call_e4a8a52c6db04cafb6a744f3727c456b", "output": "{\"status\":\"failed\",\"error\":\"INVALID_REQUEST: image url could not be downloaded\",\"created_at\":\"2026-10-17T06:12:00Z\"}" }
  ],
  "tools": [ { "type": "function", "name": "get_task_status", "description": "Look up the status of an async generation task by id.", "parameters": { "type": "object", "properties": { "task_id": { "type": "string" } }, "required": ["task_id"], "additionalProperties": false } } ],
  "reasoning": { "effort": "low" },
  "stream": true
}

With the result in hand, it answered in plain language (verbatim):

Task task_abc123 is no longer pending—it failed because the image URL could not be downloaded (INVALID_REQUEST). Check that the image URL is publicly accessible, then resubmit the task.

The call_id is the glue: your function_call_output must echo the exact call_id from the model's function_call, or the follow-up turn won't bind to it.

Recipe 5 — Grounded answers over long context

The 1.05M-token window is for feeding real material — logs, a changelog, a spec — and asking questions answered from it. The prompt pattern that keeps it honest lives in instructions: force it to answer only from the supplied text and to cite where each fact came from.

{
  "model": "gpt-6.1-sol",
  "instructions": "Answer strictly from the provided CHANGELOG. If a fact is not present, say 'not in the changelog'. Cite the date of each fact you use.",
  "input": [
    { "type": "message", "role": "user", "content": [
      { "type": "input_text", "text": "<CHANGELOG pasted here>\nQuestion: A video task's output URL returned my file yesterday but 404s today, and separately my image calls just started returning 402. What two changelog entries explain this, and what should I change?" }
    ] }
  ],
  "reasoning": { "effort": "medium" },
  "stream": true
}

Given a short platform changelog, it pulled exactly the two relevant entries, cited their dates, and separated "what happened" from "what to change" (verbatim):

Two entries explain the issues:

1. 2026-10-02 — Temporary output URLs expire. Output URLs on temp.hiapi.ai live for 7 days, then return 404 … Change: Download the bytes immediately and store your own copy; do not hotlink. Use expireAt to track expiration.

2. 2026-09-20 — Empty balances trigger image-model 402s. An account with a fully empty balance now receives HTTP 402 on all image models … Change: Check whether your account balance is fully empty and replenish it if so.

The "cite the date" instruction is the cheap grounding trick: it makes hallucinations visible (a fact with no date to point at is a fact it invented) and makes the answer auditable. Keep in mind the tiered pricing — a prompt whose input crosses 272K tokens is billed at the higher long-context rate.

One gotcha from this run: decode the stream as UTF-8

A reasoning model loves em-dashes and smart quotes. While writing this article, our first SSE reader split a multi-byte UTF-8 character across two network chunks and turned a clean em-dash ("—") into mojibake ("â"). The model's output was fine; the client was decoding per line too eagerly. The fix is to buffer raw bytes, split on newlines, and decode each complete line as UTF-8 — don't decode partial chunks. If your gpt-6.1-sol output shows stray Ã/â characters, this is why, not the model.

FAQ

What's the difference between this and the gpt-6.1-sol setup guide? The setup guide is about calling the model — auth, why streaming is mandatory, parsing SSE. This page is about prompting it — the instructions/input/effort patterns for specific jobs, with the outputs they produced.

Can I just raise reasoning.effort to max to get the best answer? Not for free, and often not for better. On our test problem, xhigh and max both plateaued near 620 reasoning tokens and returned the same answer as high. Reasoning tokens bill as output, so maxing an easy prompt costs more for an identical result. Reserve high+ for genuinely hard reasoning.

How do I force valid JSON instead of asking for it in the prompt? Pass text.format with a strict json_schema (Recipe 3). The model is constrained to the schema's types and required keys. Parse by key name, since strict doesn't fix key order.

Why can't I set temperature or top_p? This execution profile disables both (and max_output_tokens). Shape output through instructions, your input, and reasoning.effort instead.

Does tool calling work the same as on chat models? The contract is a bit different: tools are declared in a top-level tools array, the model replies with a function_call item (not a message), and you continue by appending a function_call_output with the matching call_id (Recipe 4).

Is gpt-6.1-sol the same as gpt-5.6-sol? They're the same Sol family and share this Responses-API, streaming-only contract; gpt-6.1-sol is the newer generation. See the gpt-6 Astra vs gpt-5.6 Sol comparison for how the generations line up.

Start here

Copy any recipe above into the request body from the setup guide, swap in your own task, and tune reasoning.effort to the difficulty. Capabilities and an online try-it box live on the gpt-6.1-sol model page; endpoints and the shared request format are in the API docs; per-token rates are on the pricing page. One hiapi key reaches gpt-6.1-sol and every other model on the platform.

Generate it with HiAPI

Choose a model, enter your prompt, and see the result.

HiAPI Blog

Related articles

HiAPI

Generate it with HiAPI

Start generating