必ず最初に
Responses API を使用してください。これは OpenAI の主力 API であり、
最新のモデルの動作、組み込みツール、
ステートフルなワークフロー、エージェント機能を利用するのに最適です。
すべてのリクエストを最も高性能なモデルに送るのではなく、
ワークロードに合った GPT-5.6 モデル を選びます。フラッグシップモデルの能力が必要なら gpt-5.6 または
gpt-5.6-sol、低価格で高い性能を求めるなら gpt-5.6-terra、
大量の処理を効率よく実行するなら gpt-5.6-luna を使用します。
移行時の最初の比較では、現在のモデルがワークロードで担っている役割と、実効的な推論強度を維持します。プロンプトを変更したり、新しい機能を追加したりする前に、代表的な評価を実施してください。タスクの成功状況、レイテンシ、入力・出力・推論・キャッシュ書き込みの各トークン数、成功したタスクあたりのコストを比較します。
reasoning.effort を使って、
モデルが回答前にどの程度考えるかを設定します。
GPT-5.6 モデルでサポートされている値は none、low、medium、high、
xhigh、max です。デフォルトは medium です。推論強度を下げると処理が速くなり、
推論トークンの使用量も減ります。推論強度を上げると、モデルは計画、
デバッグ、情報の統合、複数ステップにわたるトレードオフの検討に、より多くの時間をかけられます。
抽出、ルーティング、分類、定型的な書き換えが中心のタスクでは、low を使用します。
問題の診断、選択肢の比較、計画の作成、コードについての推論が必要な場合は、
medium または high を使用します。xhigh または
max は、レイテンシやコストの増加に見合う品質向上が
代表的な評価で確認された場合にのみ使用します。GPT-5.5 または GPT-5.4 から移行する際は、
現在の推論強度を出発点として、その設定と 1 段階低い設定を比較してください。
GPT-5.6 は、より少ない推論トークンで品質を維持または向上できることが多いため、
低い設定にするとレイテンシとコストも削減できる可能性があります。
品質を最優先する特に難しいワークロードでは、
reasoning.mode: "pro" と標準モードも、
同じ推論強度で比較してください。推論モードと推論強度は独立した設定です。
Pro モードでは、最終的な回答を 1 つ返す前にモデルがより多くの処理を行うことで、
信頼性を高められる可能性がありますが、レイテンシとトークン使用量は増えます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import OpenAI from "openai";
const openai = new OpenAI();
const prompt = [
"Our CI job started failing after a dependency bump.",
"",
"Error:",
"TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'",
"",
"Identify the likeliest root cause and the smallest safe fix.",
].join("\n");
const response = await openai.responses.create({
model: "gpt-6-astra",
reasoning: { effort: "xhigh", mode: "pro" },
input: prompt,
});
console.log(response.output_text); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 from openai import OpenAI
client = OpenAI()
prompt = """
Our CI job started failing after a dependency bump.
Error:
TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'
Identify the likeliest root cause and the smallest safe fix.
"""
response = client.responses.create(
model = "gpt-6-astra" ,
reasoning = { "effort" : "xhigh" , "mode" : "pro" },
input = prompt,
)
print (response.output_text) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package main
import (
"context"
"fmt"
"strings"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
prompt := strings.Join([]string{
"Our CI job started failing after a dependency bump.",
"",
"Error:",
"TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'",
"",
"Identify the likeliest root cause and the smallest safe fix.",
}, "\n")
reasoning := shared.ReasoningParam{Effort: shared.ReasoningEffortXhigh}
reasoning.SetExtraFields(map[string]any{"mode": "pro"})
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Reasoning: reasoning,
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(prompt)},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.Reasoning;
import com.openai.models.ReasoningEffort;
import com.openai.models.responses.ResponseCreateParams;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input(
"Our CI job started failing after a dependency bump. Error: TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'. Identify the likeliest root cause and the smallest safe fix.")
.reasoning(
Reasoning.builder()
.effort(ReasoningEffort.XHIGH)
.putAdditionalProperty("mode", JsonValue.from("pro"))
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text())); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 require "openai"
client = OpenAI::Client.new
prompt = <<~PROMPT
Our CI job started failing after a dependency bump.
Error:
TypeError: Timeout.__init__() got an unexpected keyword argument 'connect'
Identify the likeliest root cause and the smallest safe fix.
PROMPT
response = client.responses.create(
model: "gpt-6-astra",
reasoning: {
effort: :xhigh,
mode: :pro
},
input: prompt
)
puts(response.output_text)
text.verbosity の設定
text.verbosity は、簡潔さと情報の網羅性のバランスを調整する主な設定です。
プロダクトに素早く短い回答が必要な場合は詳細度を下げ、
より詳しい説明、明確な構成、
十分な背景情報が必要な場合は詳細度を上げます。詳細度を下げると出力トークン数が減るため、
モデルの生成量が少なくなり、出力がより速く返されます。
コーディングでは、medium と high は、より長く、整理されていて構成が明確な出力を生成する傾向があります。
low では、回答がより簡潔で必要最小限になります。
GPT-5.6 は、デフォルトで GPT-5.5 より簡潔に回答する傾向があります。移行時には、
「簡潔にしてください」のような大まかな指示が引き続き役立つかを確認してください。こうした指示によって、
回答が短くなりすぎる場合もあります。効果がある場合にのみ指示を残し、
デフォルトの詳細度は、できるだけ text.verbosity で調整してください。そのうえで、プロンプトを使って
必要な内容や構成を指定し、必要に応じて長さをより具体的に指定します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import OpenAI from "openai";
const openai = new OpenAI();
const incident = [
"Summarize this incident for the next on-call engineer.",
"- checkout latency spiked from 220 ms to 4.8 s",
"- only us-east-1 was affected",
"- rollback is complete",
"- likely trigger: cache stampede after deploy",
].join("\n");
const response = await openai.responses.create({
model: "gpt-6-astra",
text: { verbosity: "low" },
input: incident,
});
console.log(response.output_text); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model = "gpt-6-astra" ,
text = { "verbosity" : "low" },
input = """
Summarize this incident for the next on-call engineer.
- checkout latency spiked from 220 ms to 4.8 s
- only us-east-1 was affected
- rollback is complete
- likely trigger: cache stampede after deploy
""" ,
)
print (response.output_text) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package main
import (
"context"
"fmt"
"strings"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
incident := strings.Join([]string{
"Summarize this incident for the next on-call engineer.",
"- checkout latency spiked from 220 ms to 4.8 s",
"- only us-east-1 was affected",
"- rollback is complete",
"- likely trigger: cache stampede after deploy",
}, "\n")
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Text: responses.ResponseTextConfigParam{Verbosity: "low"},
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(incident)},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseTextConfig;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input(
"Summarize this incident for the next on-call engineer: checkout latency spiked from 220 ms to 4.8 s, only us-east-1 was affected, rollback is complete, and the likely trigger was a cache stampede.")
.text(ResponseTextConfig.builder().verbosity(ResponseTextConfig.Verbosity.LOW).build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text())); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 require "openai"
client = OpenAI::Client.new
incident = <<~INCIDENT
Summarize this incident for the next on-call engineer.
- checkout latency spiked from 220 ms to 4.8 s
- only us-east-1 was affected
- rollback is complete
- likely trigger: cache stampede after deploy
INCIDENT
response = client.responses.create(
model: "gpt-6-astra",
text: { verbosity: :low },
input: incident
)
puts(response.output_text)
phase は、会話履歴内のアシスタントのメッセージに付けるラベルです。
過去のアシスタントのメッセージが作業途中の報告だったのか、
最終的な回答だったのかをモデルに示します。進捗報告、
ツール呼び出し前の説明、その他の途中経過のメッセージには phase: "commentary" を使用します。
完成した応答には phase: "final_answer" を使用します。
たとえば、アシスタントが次のように伝えることがあります。
1
2
3
4
5 {
"role" : "assistant" ,
"phase" : "commentary" ,
"content" : "I'm checking the logs and comparing them to the last successful deploy."
}
これは回答ではなく、進捗報告です。その後、アシスタントが次のように伝えることがあります。
1
2
3
4
5 {
"role" : "assistant" ,
"phase" : "final_answer" ,
"content" : "The deploy failed because the migration referenced a column that does not exist in production."
}
これは、アシスタントが完了前にユーザーに見える進捗報告を行うことがある、
長時間実行のワークフローやツールを多用するワークフローで役立ちます。
gpt-5.3-codex 以降のモデルへの後続リクエストでその履歴を再送する際は、
アシスタントメッセージの phase を保持して再送してください 。これにより、モデルは
進捗報告と最終結果を区別できます。途中での早期停止を減らし、
エージェントが最終回答に到達するまで処理を続けやすくなります。
リクエストごとにツールカタログ全体を読み込む代わりに、
ツール検索 を使用します。
{"type": "tool_search"} を追加し、読み込みコストの高いツール定義に
defer_loading: true を設定します。これにより、モデルは実行時に必要なツールだけを読み込めます。
リクエスト開始時にモデルが参照できるのは、検索ツールの名前と説明だけです。
モデルが遅延読み込み対象のツールを必要と判断すると、ツール検索を実行し、
その時点で初めて対象のツール定義がコンテキストに読み込まれます。モデルがそれらを呼び出すのは、
読み込み後です。これにより、トークンを節約し、キャッシュ性能を維持できます。
ツール検索には、次の 2 つのモードがあります。
ホスト型ツール検索 は、よりシンプルな選択肢です。
リクエストで利用可能なツールの候補があらかじめ分かっている場合に使用します。
クライアント実行型ツール検索 は、アプリ側で利用可能なツールを決める必要がある場合に使用します。
たとえば、ユーザーのテナント、プロジェクト、権限、
内部レジストリに基づいて判断する場合です。
アプリ自身でツールの検出を制御する必要が本当にある場合を除き、
まずホスト型ツール検索を使用してください 。
ユーザーの意図に沿ってツールをグループ化します。可能であれば、名前空間や MCP サーバーを使用してください。モデルにとっては、関数を並べただけの長いリストよりも、明確に分けられた少数のグループから選ぶ方が容易です。トークン効率とモデル性能を最適化するため、各名前空間の関数はおおむね 10 個未満に抑えることをお勧めします。
名前空間の説明は短くし、他との違いが分かる内容にします。詳細な指示は、遅延読み込み対象のツール定義に記載してください。すべてを 1 つの巨大な名前空間にまとめることは避けます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 import OpenAI from "openai";
const openai = new OpenAI();
const billingNamespace = {
type: "namespace",
name: "billing",
description: "Billing tools for invoices, payments, taxes, and credits.",
tools: [
{
type: "function",
name: "lookup_invoice",
description:
"Look up invoice state, taxes, credits, and payment attempts.",
parameters: {
type: "object",
properties: {
invoice_id: { type: "string" },
},
required: ["invoice_id"],
additionalProperties: false,
},
strict: true,
defer_loading: true,
},
],
};
const crmNamespace = {
type: "namespace",
name: "crm",
description:
"CRM tools for account ownership, plans, health, and payment history.",
tools: [
{
type: "function",
name: "get_account",
description: "Fetch account owner, plan, health, and payment history.",
parameters: {
type: "object",
properties: {
account_id: { type: "string" },
},
required: ["account_id"],
additionalProperties: false,
},
strict: true,
defer_loading: true,
},
],
};
const response = await openai.responses.create({
model: "gpt-6-astra",
input:
"Find the right billing tool and explain why invoice INV-1043 still " +
"shows overdue after a payment yesterday.",
tools: [billingNamespace, crmNamespace, { type: "tool_search" }],
});
console.log(response.output); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 from openai import OpenAI
client = OpenAI()
billing_namespace = {
"type" : "namespace" ,
"name" : "billing" ,
"description" : "Billing tools for invoices, payments, taxes, and credits." ,
"tools" : [
{
"type" : "function" ,
"name" : "lookup_invoice" ,
"description" : "Look up invoice state, taxes, credits, and payment attempts." ,
"parameters" : {
"type" : "object" ,
"properties" : {
"invoice_id" : { "type" : "string" },
},
"required" : [ "invoice_id" ],
"additionalProperties" : False ,
},
"strict" : True ,
"defer_loading" : True ,
}
],
}
crm_namespace = {
"type" : "namespace" ,
"name" : "crm" ,
"description" : "CRM tools for account ownership, plans, health, and payment history." ,
"tools" : [
{
"type" : "function" ,
"name" : "get_account" ,
"description" : "Fetch account owner, plan, health, and payment history." ,
"parameters" : {
"type" : "object" ,
"properties" : {
"account_id" : { "type" : "string" },
},
"required" : [ "account_id" ],
"additionalProperties" : False ,
},
"strict" : True ,
"defer_loading" : True ,
}
],
}
response = client.responses.create(
model = "gpt-6-astra" ,
input = (
"Find the right billing tool and explain why invoice INV-1043 still "
"shows overdue after a payment yesterday."
),
tools = [billing_namespace, crm_namespace, { "type" : "tool_search" }],
)
print (response.output) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
billing := namespaceTool(
"billing",
"Billing tools for invoices, payments, taxes, and credits.",
"lookup_invoice",
"Look up invoice state, taxes, credits, and payment attempts.",
"invoice_id",
)
crm := namespaceTool(
"crm",
"CRM tools for account ownership, plans, health, and payment history.",
"get_account",
"Fetch account owner, plan, health, and payment history.",
"account_id",
)
toolSearch := responses.ToolUnionParam{OfToolSearch: &responses.ToolSearchToolParam{}}
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(
"Find the right billing tool and explain why invoice INV-1043 still shows overdue after a payment yesterday.",
)},
Tools: []responses.ToolUnionParam{billing, crm, toolSearch},
})
if err != nil {
panic(err)
}
fmt.Println(response.Output)
}
func namespaceTool(namespace, namespaceDescription, name, description, argument string) responses.ToolUnionParam {
parameters := map[string]any{
"type": "object",
"properties": map[string]any{
argument: map[string]any{"type": "string"},
},
"required": []string{argument},
"additionalProperties": false,
}
function := responses.NamespaceToolToolFunctionParam{
Name: name, Description: openai.String(description), Parameters: parameters, Strict: openai.Bool(true), DeferLoading: openai.Bool(true),
}
return responses.ToolParamOfNamespace(
namespaceDescription,
namespace,
[]responses.NamespaceToolToolUnionParam{{OfFunction: &function}},
)
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.NamespaceTool;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ToolSearchTool;
import java.util.List;
import java.util.Map;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input(
"Find the right billing tool and explain why invoice INV-1043 still shows overdue after a payment yesterday.")
.addTool(
namespace(
"billing",
"Billing tools for invoices, payments, taxes, and credits.",
"lookup_invoice",
"Look up invoice state, taxes, credits, and payment attempts.",
"invoice_id"))
.addTool(
namespace(
"crm",
"CRM tools for account ownership, plans, health, and payment history.",
"get_account",
"Fetch account owner, plan, health, and payment history.",
"account_id"))
.addTool(ToolSearchTool.builder().execution(ToolSearchTool.Execution.SERVER).build())
.build();
client.responses().create(params).output().forEach(System.out::println);
private static NamespaceTool namespace(
String name,
String description,
String function,
String functionDescription,
String argument) {
return NamespaceTool.builder()
.name(name)
.description(description)
.addTool(
NamespaceTool.Tool.Function.builder()
.name(function)
.description(functionDescription)
.deferLoading(true)
.strict(true)
.parameters(
JsonValue.from(
Map.of(
"type",
"object",
"properties",
Map.of(argument, Map.of("type", "string")),
"required",
List.of(argument),
"additionalProperties",
false)))
.build())
.build();
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 require "openai"
def namespace_tool(name, description, function_name, function_description, argument)
{
type: :namespace,
name: name,
description: description,
tools: [
{
type: :function,
name: function_name,
description: function_description,
defer_loading: true,
strict: true,
parameters: {
type: "object",
properties: { argument => { type: "string" } },
required: [argument],
additionalProperties: false
}
}
]
}
end
client = OpenAI::Client.new
billing = namespace_tool(
"billing",
"Billing tools for invoices, payments, taxes, and credits.",
"lookup_invoice",
"Look up invoice state, taxes, credits, and payment attempts.",
"invoice_id"
)
crm = namespace_tool(
"crm",
"CRM tools for account ownership, plans, health, and payment history.",
"get_account",
"Fetch account owner, plan, health, and payment history.",
"account_id"
)
response = client.responses.create(
model: "gpt-6-astra",
input: "Find the right billing tool and explain why invoice INV-1043 still shows overdue after a payment yesterday.",
tools: [billing, crm, { type: :tool_search }]
)
puts(response.output)
プログラムによるツール呼び出し を使用すると、
GPT-5.6 が JavaScript を記述して対象ツールを呼び出し、
ホスト型ランタイム内で中間結果を小さくまとめられます。大量のツール結果に対して、
コードでフィルタリング、結合、順位付け、重複排除、統合、検証などを行い、
モデルに小さな構造化結果を返せる、範囲の明確な処理段階で使用します。
programmatic_tool_calling ツールを追加し、対象となる各ツールで利用を明示的に有効にします。
プログラムからのみ呼び出すツールには allowed_callers: ["programmatic"] を使用し、
モデルから直接呼び出すことも許可する場合は allowed_callers: ["direct", "programmatic"] を使用します。
個々の結果がモデルの次の判断を変え得る場合、
アクションに承認が必要な場合、または最終回答に引用やネイティブの成果物を保持する必要がある場合は、
直接呼び出しを使用してください。ツールの戻り値のフィールドとエラー時の動作を文書化し、
モデルが結果を事前に確認しなくても正しいプログラムを記述できるようにします。
ツールループでは、program と program_output の項目に加えて、
プログラムが発行する function_call 項目と、それに対応する function_call_output 項目も処理する必要があります。
各 call_id を保持し、関数呼び出しの caller をその出力にコピーして、
サービスが正しいプログラムを再開できるようにします。
program_output とアシスタントの最終メッセージの両方をテストします。
プログラムの結果が正しくても、最終回答が不完全になることはあります。
ツールを直接呼び出す同じワークフローと比較して、タスクの成功、必要な根拠、
合計トークン数、レイテンシ、コストを評価してください。
マルチエージェント は GPT-5.6 の機能で、
ルートエージェントが独立した作業をサブエージェントに委任し、
その結果を統合できます。リサーチ、分析、実装を、
個別のコンテキストを使って並列に実行できる、具体的で範囲の明確なタスクに分割できる場合に使用します。
リクエストで multi_agent.enabled を true に設定します。HTTP の場合は、
ベータ版の Responses SDK で client.beta.responses を使用し、
betas に responses_multi_agent=v1 を渡します。HTTP を直接使用する場合や WebSocket 接続の場合は、
OpenAI-Beta: responses_multi_agent=v1 を送信します。マルチエージェントがベータ版の間は、
項目のスキーマが変更される可能性があります。
短いタスク、各ステップが直前のステップに依存する一連の処理、
同じ変更可能なリソースに書き込む作業には、単一のエージェントを優先してください。
サブエージェントはトークン使用量を増やす可能性があるため、まず max_concurrent_subagents をデフォルトの 3 にして、
処理全体の品質、レイテンシ、コストを測定します。ツールを多用する、または長時間実行される
マルチエージェントのワークフローでは、WebSocket モードで処理継続時のオーバーヘッドを削減できます。
マルチエージェントを有効にする前に、現在の制約を考慮してください。
/responses/compact、reasoning.summary、max_tool_calls はサポートされていません。
サーバーはルートのコンテキストと、
すべてのサブエージェントのコンテキストに対して自動的にコンパクションを行います。
組み込みツール は、API に標準で備わっている機能です。
すべてのツールを自作しなくても、Responses API 内ですでに動作するツールを
モデルに利用させることができます。モデルは、
それらを使用するタイミングを判断できます。
OpenAI は標準のツールを継続的に追加しているため、ワークフローに合う組み込みツールがあれば、まずそれを使用してください。標準のツールでタスクに対応できない場合は、カスタムツールを作成します。現在の組み込みツールと関連するツールの選択肢には、次のものがあります。
ウェブ検索 :ウェブで最新情報を検索
ファイル検索 :アップロード済みのファイルやベクトルストアを検索
Code Interpreter :Python を実行し、分析、数学計算、グラフ作成、
ファイル処理を実施
シェル :ホスト型コンテナまたは独自のランタイムでシェルコマンドを実行
コンピューターの使用 :スクリーンショット、クリック、文字入力、
スクロールを通じて UI を操作
画像生成 :画像の生成や編集
MCP / コネクタ :モデルを外部サービスやツールに接続
スキル :再利用可能な指示のセットやワークフローファイルを添付
パッチの適用 :構造化された形式でコードを編集
モデルの品質も、組み込みツールを優先する理由の 1 つです。組み込みツールは OpenAI の事後学習のデータ分布に含まれています。つまり、モデルはこれらのツールの形式、動作、出力を使って学習・評価されています。そのため、OpenAI のモデルは、新しいツールを使う場合に比べて、組み込みツールではより適切にツールを選択し、より円滑に実行でき、失敗も少なくなります。
コンパクション はコンテキストエンジニアリングのツールで、
モデルが多くのターンにわたって引き継ぐ情報を決めます。
長時間実行されるエージェントでは、「コンテキストの上限に達するかどうか」だけが問題ではありません。
過去のメッセージ、ツールのログ、再試行、古くなった詳細情報によって、
モデルが必要とする状態情報が埋もれてしまうことも問題です。
コンパクションを使うと、後続のターンに必要な状態を保持しながら、コンテキストのサイズを制御して縮小できます。デバッグの一区切りや根本原因の絞り込みなど、意味のある節目で、それまでのコンテキストウィンドウにコンパクションを行い、その出力から処理を続けられます。次のターンが、中間的な推論、失敗したコマンド、不要になった推論の分岐をすべて含むのではなく、重要な状態を中心に構成されるため、モデルの判断力を維持できます。
コンパクションには、次の 2 つの利用方法があります。
サーバーに任せる :previous_response_id を使用する場合は、
compact_threshold を指定して context_management を有効にします。
会話が大きくなりすぎると、サーバーが自動的にコンパクションを行います。
引き続き、最新のユーザーメッセージだけを送信すれば済みます。
自分で処理する :入力配列全体を自分で管理している場合は、
client.responses.compact() を呼び出します。小さくなったコンテキストウィンドウが返されるので、
その出力を次の responses.create() 呼び出しでそのまま使用します。
コンパクション後の出力は編集しないでください。 これは人間向けの要約ではなく、
モデルの処理継続を支える機械用の状態情報です。そのまま引き継いだうえで、
次のユーザーメッセージを追加してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import OpenAI from "openai";
import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";
const openai = new OpenAI();
// Full window collected from a long debugging session:
// user messages, assistant outputs, tool calls, and tool outputs.
const longWindow = sessionItems;
const compacted = await openai.responses.compact({
model: "gpt-6-astra",
input: longWindow,
});
const nextResponse = await openai.responses.create({
model: "gpt-6-astra",
store: false,
input: [
// Preserve replayable compacted items.
...toResponseInputItems(compacted.output),
{
type: "message",
role: "user",
content:
"We found the bad cache invalidation path. Write the fix plan " +
"and the verification checklist.",
},
],
});
console.log(nextResponse.output_text); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 from openai import OpenAI
client = OpenAI()
# Full window collected from a long debugging session:
# user messages, assistant outputs, tool calls, and tool outputs.
long_window = session_items
compacted = client.responses.compact(
model = "gpt-6-astra" ,
input = long_window,
)
next_response = client.responses.create(
model = "gpt-6-astra" ,
store = False ,
input = [
* compacted.output, # Use compact output as-is.
{
"type" : "message" ,
"role" : "user" ,
"content" : (
"We found the bad cache invalidation path. Write the fix plan "
"and the verification checklist."
),
},
],
)
print (next_response.output_text) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 package main
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
longWindow := []responses.ResponseInputItemUnionParam{
responses.ResponseInputItemParamOfMessage("Find the cache invalidation bug in this debugging session.", responses.EasyInputMessageRoleUser),
}
compacted, err := client.Responses.Compact(context.Background(), responses.ResponseCompactParams{
Model: "gpt-6-astra",
Input: responses.ResponseCompactParamsInputUnion{OfResponseInputItemArray: longWindow},
})
if err != nil {
panic(err)
}
input := append(outputAsInput(compacted.Output),
responses.ResponseInputItemParamOfMessage(
"We found the bad cache invalidation path. Write the fix plan and the verification checklist.",
responses.EasyInputMessageRoleUser,
),
)
nextResponse, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Store: openai.Bool(false),
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: input},
})
if err != nil {
panic(err)
}
fmt.Println(nextResponse.OutputText())
}
func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {
input := make([]responses.ResponseInputItemUnionParam, 0, len(output))
for _, item := range output {
var converted responses.ResponseInputItemUnion
if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {
panic(err)
}
input = append(input, converted.ToParam())
}
return input
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCompactParams;
import com.openai.models.responses.ResponseCompactionItemParam;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputItem;
import java.util.ArrayList;
var compacted =
client
.responses()
.compact(
ResponseCompactParams.builder()
.model("gpt-6-astra")
.input("Find the cache invalidation bug in this debugging session.")
.build());
var input = new ArrayList<ResponseInputItem>();
for (var item : compacted.output()) {
item.message().map(ResponseInputItem::ofResponseOutputMessage).ifPresent(input::add);
item.reasoning().map(ResponseInputItem::ofReasoning).ifPresent(input::add);
item.compaction()
.map(
value ->
ResponseInputItem.ofCompaction(
ResponseCompactionItemParam.builder()
.id(value.id())
.encryptedContent(value.encryptedContent())
.build()))
.ifPresent(input::add);
}
input.add(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content(
"We found the bad cache invalidation path. Write the fix plan and the verification checklist.")
.build()));
client
.responses()
.create(
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(input)
.store(false)
.build())
.output()
.stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text())); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 require "openai"
client = OpenAI::Client.new
long_window = [
{
role: :user,
content: "Find the cache invalidation bug in this debugging session."
}
]
compacted = client.responses.compact(
model: "gpt-6-astra",
input: long_window
)
input = compacted.output.dup
input << {
role: :user,
content: "We found the bad cache invalidation path. Write the fix plan and the verification checklist."
}
response = client.responses.create(
model: "gpt-6-astra",
store: false,
input: input
)
puts(response.output_text)
プロンプトキャッシュ は、リクエスト間で同じ長いプレフィックスを再利用する際に、
レイテンシとコストを自動的に削減します。変化しない指示、
例、参考資料を先頭に配置し、その後にユーザー固有の動的なコンテンツを
続けます。ツールの定義と順序は一定に保ち、
以前のコンテキストを書き換えずに、新しい会話ターンを末尾に追加してください。
GPT-5.6 では、明示的なプロンプトキャッシュが導入されました。
デフォルトは引き続き暗黙的なキャッシュですが、GPT-5.6 モデルとそれ以降のモデルファミリーでは、
明示的なキャッシュブレークポイントとリクエスト全体のキャッシュポリシーもサポートしています。
変化しないプレフィックスの後に変化するサフィックスが続く場合は、再利用可能な部分の境界に prompt_cache_breakpoint を明示的に追加します。
指定したブレークポイントだけを使用し、暗黙的なブレークポイントを使用しない場合にのみ、
prompt_cache_options.mode を explicit に設定してください。それ以前のモデルでは、
引き続き自動プロンプトキャッシュのみを使用します。
GPT-5.6 モデルとそれ以降のモデルファミリーでは、キャッシュへの書き込み料金は、
キャッシュされていない入力トークン料金の 1.25 倍です。cached_tokens と cache_write_tokens を記録し、
書き込み量とその後のキャッシュ読み取り量を比較して、実質的なコストを測定し、
ブレークポイントの配置を調整してください。
GPT-5.6 より前のモデルでは、再利用可能なプレフィックスを共有するリクエストに同じ prompt_cache_key を使い続けることで、
関連するリクエストを同じキャッシュにルーティングしやすくなり、
キャッシュヒット率を最適化できます。トラフィックの多いグループでは、より多くのキーにトラフィックを分散するための
ガイダンス に従ってください。
GPT-5.6 以降では、prompt_cache_key は任意です。指定しなくても、
最適なキャッシュヒット率を達成できます。このキーを使うと、
顧客、ユーザー、ワークスペースごとにキャッシュ使用量を個別に集計できます。これにより、
各グループのキャッシュ済みトークン使用量と請求額を説明しやすくなります。顧客ごとに固有のキーを割り当て、
その顧客の関連リクエストでは同じキーを使い続けてください。キーを分けることは、
顧客間でキャッシュヒットの有無を探る行為の防止にも役立ちます。キーによる
キャッシュ集計の分離 を参照してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import OpenAI from "openai";
const openai = new OpenAI();
const instructions = [
"You are the support agent for Acme.",
"Follow the Acme support policy and escalation rubric.",
"Use the same tone, safety rules, and tool plan for each ticket.",
].join("\n");
const response = await openai.responses.create({
model: "gpt-6-astra",
prompt_cache_key: "tenant-acme-support-agent",
instructions,
input: "Summarize the current escalation for the on-call lead.",
});
console.log(response.output_text); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 from openai import OpenAI
client = OpenAI()
instructions = """
You are the support agent for Acme.
Follow the Acme support policy and escalation rubric.
Use the same tone, safety rules, and tool plan for each ticket.
"""
response = client.responses.create(
model = "gpt-6-astra" ,
prompt_cache_key = "tenant-acme-support-agent" ,
instructions = instructions,
input = "Summarize the current escalation for the on-call lead." ,
)
print (response.output_text) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package main
import (
"context"
"fmt"
"strings"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
instructions := strings.Join([]string{
"You are the support agent for Acme.",
"Follow the Acme support policy and escalation rubric.",
"Use the same tone, safety rules, and tool plan for each ticket.",
}, "\n")
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
PromptCacheKey: openai.String("tenant-acme-support-agent"),
Instructions: openai.String(instructions),
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Summarize the current escalation for the on-call lead.")},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.ResponseCreateParams;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.instructions(
"You are the support agent for Acme.\n"
+ "Follow the Acme support policy and escalation rubric.\n"
+ "Use the same tone, safety rules, and tool plan for each ticket.")
.input("Summarize the current escalation for the on-call lead.")
.promptCacheKey("tenant-acme-support-agent")
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text())); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
PromptCacheKey = "tenant-acme-support-agent",
Instructions = "Follow the Acme support policy and escalation rubric.",
};
options.InputItems.Add(
ResponseItem.CreateUserMessageItem("Summarize the current escalation for the on-call lead.")
);
ResponseResult response = await client.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText()); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 require "openai"
client = OpenAI::Client.new
instructions = <<~INSTRUCTIONS
You are the support agent for Acme.
Follow the Acme support policy and escalation rubric.
Use the same tone, safety rules, and tool plan for each ticket.
INSTRUCTIONS
response = client.responses.create(
model: "gpt-6-astra",
prompt_cache_key: "tenant-acme-support-agent",
instructions: instructions,
input: "Summarize the current escalation for the on-call lead."
)
puts(response.output_text)
reasoning.encrypted_content の使用
GPT-5.6 は、呼び出し間で
推論を保持 できます。
タスクの目標、前提、優先順位が変わらない場合は、
reasoning.context: "all_turns" を使用します。以前の推論がもはや関係なく、
モデルが古いアプローチに引きずられるおそれがある場合は、current_turn を使用します。
reasoning.context を省略するか auto に設定した場合は、レスポンスの
reasoning.context フィールドを調べて、実際に適用されたモードを確認してください。
推論の保持 が機能するのは、
以前の推論項目を利用できる場合に限られます。保存済みのレスポンスには previous_response_id を
使用します。ゼロデータ保持
(ZDR) の要件によって、
レスポンスデータを保存できない場合は、暗号化された推論内容を使うことで、
ステートレスな引き継ぎが可能になります。
レスポンス出力の推論項目には、デフォルトで暗号化された推論内容が
含まれます。暗号化された推論内容には、各推論項目の
encrypted_content プロパティからアクセスできます。アプリ側でその値の意味を解釈する必要は
ありません。各推論項目を返されたとおりに保持し、
次のターンで再送するだけで、モデルがその内容を使ってワークフローを続行できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import OpenAI from "openai";
import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";
const openai = new OpenAI();
const history = [
{
role: "user",
content: "Investigate why invoice INV-1043 has mismatched tax totals.",
},
];
const first = await openai.responses.create({
model: "gpt-6-astra",
store: false,
reasoning: { effort: "medium", context: "current_turn" },
input: history,
});
history.push(...toResponseInputItems(first.output));
history.push({
role: "user",
content: "Now write the customer-facing explanation in plain English.",
});
const second = await openai.responses.create({
model: "gpt-6-astra",
store: false,
reasoning: { effort: "medium", context: "all_turns" },
input: history,
});
console.log(second.output_text); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 from openai import OpenAI
client = OpenAI()
history = [
{
"role" : "user" ,
"content" : "Investigate why invoice INV-1043 has mismatched tax totals." ,
}
]
first = client.responses.create(
model = "gpt-6-astra" ,
store = False ,
reasoning = { "effort" : "medium" , "context" : "current_turn" },
input = history,
)
history.extend(item.model_dump( exclude = { "status" }) for item in first.output)
history.append(
{
"role" : "user" ,
"content" : "Now write the customer-facing explanation in plain English." ,
}
)
second = client.responses.create(
model = "gpt-6-astra" ,
store = False ,
reasoning = { "effort" : "medium" , "context" : "all_turns" },
input = history,
)
print (second.output_text) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 package main
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
history := []responses.ResponseInputItemUnionParam{
responses.ResponseInputItemParamOfMessage("Investigate why invoice INV-1043 has mismatched tax totals.", responses.EasyInputMessageRoleUser),
}
first, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Store: openai.Bool(false),
Reasoning: shared.ReasoningParam{Effort: shared.ReasoningEffortMedium, Context: shared.ReasoningContextCurrentTurn},
Include: []responses.ResponseIncludable{responses.ResponseIncludableReasoningEncryptedContent},
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: history},
})
if err != nil {
panic(err)
}
history = append(history, outputAsInput(first.Output)...)
history = append(history, responses.ResponseInputItemParamOfMessage(
"Now write the customer-facing explanation in plain English.",
responses.EasyInputMessageRoleUser,
))
second, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Store: openai.Bool(false),
Reasoning: shared.ReasoningParam{Effort: shared.ReasoningEffortMedium, Context: shared.ReasoningContextAllTurns},
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: history},
})
if err != nil {
panic(err)
}
fmt.Println(second.OutputText())
}
func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {
input := make([]responses.ResponseInputItemUnionParam, 0, len(output))
for _, item := range output {
var converted responses.ResponseInputItemUnion
if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {
panic(err)
}
input = append(input, converted.ToParam())
}
return input
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.Reasoning;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseIncludable;
import com.openai.models.responses.ResponseInputItem;
import java.util.ArrayList;
var history = new ArrayList<ResponseInputItem>();
history.add(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Investigate why invoice INV-1043 has mismatched tax totals.")
.build()));
var first =
client
.responses()
.create(
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(history)
.store(false)
.reasoning(
Reasoning.builder()
.effort(com.openai.models.ReasoningEffort.MEDIUM)
.putAdditionalProperty("context", JsonValue.from("current_turn"))
.build())
.addInclude(ResponseIncludable.of("reasoning.encrypted_content"))
.build());
first.output().stream()
.map(item -> JsonValue.from(item).convert(ResponseInputItem.class))
.forEach(history::add);
history.add(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Now write the customer-facing explanation in plain English.")
.build()));
client
.responses()
.create(
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(history)
.store(false)
.reasoning(
Reasoning.builder()
.effort(com.openai.models.ReasoningEffort.MEDIUM)
.putAdditionalProperty("context", JsonValue.from("all_turns"))
.build())
.build())
.output()
.stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text())); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 require "openai"
client = OpenAI::Client.new
history = [
{
role: :user,
content: "Investigate why invoice INV-1043 has mismatched tax totals."
}
]
first = client.responses.create(
model: "gpt-6-astra",
store: false,
reasoning: {
effort: :medium,
context: :current_turn
},
include: ["reasoning.encrypted_content"],
input: history
)
history.concat(first.output)
history << {
role: :user,
content: "Now write the customer-facing explanation in plain English."
}
second = client.responses.create(
model: "gpt-6-astra",
store: false,
reasoning: {
effort: :medium,
context: :all_turns
},
input: history
)
puts(second.output_text)
GPT-5.6 モデルでは、画像の detail を省略した場合も detail: "auto" を指定した場合も、
original と同じサイズ処理が適用されます。サービスは入力画像の寸法を維持しますが、
いずれかの辺が 65,535 ピクセルを超える画像は、
その上限に収まるように縮小されます。それでも
30,000 パッチの上限 を超える画像は、
上限に合わせてリサイズされるのではなく、API によって拒否されます。大きな画像では入力トークン数が増え、
その結果、レイテンシも増加する場合があります。
タスクに合わせて detail を選択します。
画像をリサイズするか、細部の視覚情報が重要でなければ low を、
標準的な高精細の画像理解には high を使用します。
大きな画像や情報密度の高い画像の処理、座標精度が重要な処理、OCR、位置特定、
目視検査など、細部の情報が品質向上につながるタスクには original を使用します。
デプロイ前に、最悪ケースの画像トークン数とレイテンシを測定してください。
個々のエンドユーザーに提供するアプリケーションでは、
プライバシーを保護し、一貫して同じ値を使う
safety_identifier を
リクエストごとに送信します。これにより、OpenAI が不正利用を検出しやすくなり、チームでも
ポリシー違反を継続的に追跡できるようになります。また、あるユーザーの不正利用によって
組織全体のアクセスに支障が出る可能性を低減できます。
個人を特定できる情報をそのまま送信せず、ユーザー名やメールアドレスをハッシュ化してください。ログアウト状態での利用には、一貫して同じ値を使うセッション ID を使用します。
時間がかかる可能性のあるリクエストには background=True を使用します。
クライアント接続を開いたままにする代わりに、API がジョブを開始し、
ID を返します。アプリは、そのジョブが完了、失敗、またはキャンセルされるまで
ポーリングできます。大規模な分析、長時間のツール実行、ステータスの確認や
再試行の仕組みが必要な処理に使用してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 // Replace the illustrative IDs and URLs below with your own resource values.
import OpenAI from "openai";
const openai = new OpenAI();
const logBundleFileId = "file_123";
let job = await openai.responses.create({
model: "gpt-6-astra",
background: true,
store: false,
input: "Analyze this large log bundle and cluster the primary failure modes.",
tools: [
{
type: "code_interpreter",
container: {
type: "auto",
file_ids: [logBundleFileId],
},
},
],
});
while (["queued", "in_progress"].includes(job.status)) {
await new Promise((resolve) => setTimeout(resolve, 2000));
job = await openai.responses.retrieve(job.id);
}
console.log(job.output_text); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 # Replace the illustrative IDs and URLs below with your own resource values.
from openai import OpenAI
import time
client = OpenAI()
log_bundle_file_id = "file_123"
job = client.responses.create(
model = "gpt-6-astra" ,
background = True ,
store = False ,
input = "Analyze this large log bundle and cluster the primary failure modes." ,
tools = [
{
"type" : "code_interpreter" ,
"container" : {
"type" : "auto" ,
"file_ids" : [log_bundle_file_id],
},
}
],
)
while job.status in { "queued" , "in_progress" }:
time.sleep( 2 )
job = client.responses.retrieve(job.id)
print (job.output_text) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package main
import (
"context"
"fmt"
"time"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
tool := responses.ToolParamOfCodeInterpreter(responses.ToolCodeInterpreterContainerCodeInterpreterContainerAutoParam{
FileIDs: []string{"file_abc123"},
})
job, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Background: openai.Bool(true),
Store: openai.Bool(false),
Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Analyze this large log bundle and cluster the primary failure modes.")},
Tools: []responses.ToolUnionParam{tool},
})
if err != nil {
panic(err)
}
for job.Status == responses.ResponseStatusQueued || job.Status == responses.ResponseStatusInProgress {
time.Sleep(2 * time.Second)
job, err = client.Responses.Get(context.Background(), job.ID, responses.ResponseGetParams{})
if err != nil {
panic(err)
}
}
fmt.Println(job.OutputText())
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseStatus;
import com.openai.models.responses.Tool;
String fileId = "file_abc123";
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.input("Analyze this large log bundle and cluster the primary failure modes.")
.background(true)
.store(false)
.addCodeInterpreterTool(
Tool.CodeInterpreter.Container.CodeInterpreterToolAuto.builder()
.addFileId(fileId)
.build())
.build();
var response = client.responses().create(params);
while (response.status().filter(ResponseStatus.QUEUED::equals).isPresent()
|| response.status().filter(ResponseStatus.IN_PROGRESS::equals).isPresent()) {
Thread.sleep(1000);
response = client.responses().retrieve(response.id());
}
if (response.status().filter(ResponseStatus.COMPLETED::equals).isEmpty()) {
throw new IllegalStateException(
"Research ended with status: " + response.status().orElseThrow());
}
response.output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text())); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 require "openai"
client = OpenAI::Client.new
job = client.responses.create(
model: "gpt-6-astra",
background: true,
store: false,
input: "Analyze this large log bundle and cluster the primary failure modes.",
tools: [
{
type: :code_interpreter,
container: {
type: :auto,
file_ids: ["file_abc123"]
}
}
]
)
while [:queued, :in_progress].include?(job.status)
sleep(2)
job = client.responses.retrieve(job.id)
end
puts(job.output_text)
stream=True と組み合わせると進捗イベントを受け取れますが、
最初のイベントが届くまでに通常のリクエストより時間がかかる場合があります。
UI の観点では、バックグラウンドモードは「実行中です。現在のステータスはこちらです。結果は準備ができ次第ここに表示されます」という状態を表します。
WebSocket モード は、長時間実行され、ツール呼び出しの多いワークフロー向けに設計されています。
接続を開いたまま維持し、
新しい入力項目と previous_response_id だけを送信して処理を続けます。
ツール呼び出しが 20 回以上ある実行では、この方法により、
開始から完了までの処理が約 40% 高速になります。
仕組み :最初のメッセージは通常の Responses リクエストと同様に、
モデル、指示、ツール、ユーザー入力を含みます。サーバーはイベントをストリーミングで返します。
モデルがツールの使用を要求すると、アプリがそのツールを実行します。その後は、新しい
HTTP リクエストを送る代わりに、同じソケットで再び response.create イベントを送信し、
その中に前の previous_response_id と新しい項目を含めます。これが
レイテンシを短縮できる理由です。通常の HTTP では、後続の処理は毎回新しいリクエストになります。WebSocket モードでは、
接続が開いたまま維持され、最新のレスポンスの状態が、その接続に対応する
メモリ内ですぐに使える状態に保たれます。次のターンがそのレスポンスから継続する場合、
バックエンドで必要な準備処理が少なくなります。
リクエスト 1 件に対して回答 1 件で完結するワークフローなら、 引き続き HTTP を使用してください 。
長時間実行するエージェントのようなワークフローなら、WebSocket モードを試してください。
1 つの WebSocket 接続で同時に処理できるレスポンスは 1 件のため、
並列処理には複数の接続が必要です。現在、接続の最大継続時間は 60 分です。
処理の継続に使用する previous_response_id の意味と動作は HTTP モードと同じで、
最新のレスポンスは接続ごとのキャッシュに保持されます。
注:WebSocket モードでは、データはディスクに保存されず、メモリ内にのみ保持されるため、ZDR と併用できます。
Python のサンプルでは pip install "openai[realtime]>=3.8.0" を使用します。
JavaScript のサンプルでは npm install openai@^7.10.0 ws を使用します。
Ruby のサンプルでは gem install openai async-websocket を使用します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 import OpenAI from "openai";
import { ResponsesWS } from "openai/resources/responses/ws";
const openai = new OpenAI();
const ws = new ResponsesWS(openai);
ws.on("event", (event) => {
console.log(event.type);
if (
event.type === "response.completed" ||
event.type === "response.failed" ||
event.type === "response.incomplete"
) {
ws.close();
}
});
ws.on("error", (error) => {
console.error(error);
ws.close();
});
ws.send({
type: "response.create",
model: "gpt-6-astra",
store: false,
input: [
{
type: "message",
role: "user",
content: [
{
type: "input_text",
text:
"Find the flaky test in this run, call the tools you need, " +
"and keep going until you can explain the root cause.",
},
],
},
],
tools: [testLogTool, codeSearchTool],
}); 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 from openai import OpenAI
client = OpenAI()
with client.responses.connect() as connection:
# Use the same typed parameters as client.responses.create(...).
connection.response.create(
model = "gpt-6-astra" ,
store = False ,
input = [
{
"type" : "message" ,
"role" : "user" ,
"content" : [
{
"type" : "input_text" ,
"text" : (
"Find the flaky test in this run, call the tools "
"you need, and keep going until you can explain "
"the root cause."
),
}
],
}
],
tools = [test_log_tool, code_search_tool],
)
first_event = connection.recv()
print (first_event.type) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 require "async"
require "openai"
require "json"
def wait_for_response(connection)
while (event = connection.receive)
case event.type.to_s
when "response.completed" then return event.response
when "response.failed", "response.incomplete", "error"
raise "Response failed: #{event.to_json}"
end
end
raise "Connection closed before the response finished"
end
test_log_tool = {
type: "function",
name: "search_test_logs",
description: "Search test logs.",
parameters: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"],
additionalProperties: false
},
strict: true
}
code_search_tool = {
type: "function",
name: "search_code",
description: "Search source code.",
parameters: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"],
additionalProperties: false
},
strict: true
}
client = OpenAI::Client.new
Sync do |task|
task.with_timeout(120) do
client.responses.connect(request_options: { timeout: 10 }) do |connection|
connection.response.create(
stream_id: "main", model: "gpt-6-astra", store: false,
input: [
{
role: "user",
content: "Find the flaky test in this run, call the tools you need, and keep going until you can explain the root cause."
}
],
tools: [test_log_tool, code_search_tool]
)
puts(JSON.pretty_generate(wait_for_response(connection).output.map(&:to_h)))
end
end
end
Responses API は、より賢く高機能な OpenAI アプリケーションを構築するための基盤です。その大きな利点は、開発者が単発のプロンプトから、ツールとコンテキストを活用し、タスクの複雑さに対応しながら継続的に動作するワークフローへ移行できることにあります。このガイドに沿って、実際のデプロイでより高いパフォーマンスを実現してください。