tea-e7n.dev

OpenAI Agents APIをサクッと使う

9/10にOpenAIから、Agents APIという仕組みが発表され、利用可能となりました。

今回はこれについて簡単に見ていきます。

Agents APIの概要

Agents APIは、OpenAIが提供するAI Agentを取り巻く仕組みをAPIを経由して利用できるといったものになっています。

これまでにもOpenAIはAPIを経由してAgentを利用するための枠組みを用意してきましたが、それらは基本的に利用者に委ねられていたというか、Agent実行環境の準備から細かな仕組みの調整まで、原則として自前で行う必要がありました。

一方今回発表されたAgents APIでは、OpenAIが管理するCodex HarnessをAPI経由で利用できます。 またセッションやオーケストレーションについてもOpenAIが管理し、必要に応じてOpenAI hostedとself hostedの実行環境を選択して動かすことができるというものになっています。

従来はほんのちょっとしたAgentシステムをアプリケーション上に導入するだけでも、それなりに大層な仕組みが必要になっていましたが、Agents APIの利用によりハードルが一気に低くなることが期待できます。

Agents APIを使ってみる

今回は、Agents APIを利用してGitHubのIssueをAgent経由で操作するという実験をしてみようと思います。

なお、実装はGo言語を利用しています。Go言語による実装のQuickstartは公式が用意してくれていたので、ある程度はこれを参考にしました。

なお、OpenAI API Keyについてはすでに取得済みであることを前提としており、その登録手順などは記事の内容として扱うことはありません。興味がある方はご自身のお好みの方式で実装していただければと思います。

Vaultにcredential情報を登録する

今回はGitHub上の操作を行うということでGitHub MCP Serverを利用したいです。 GitHub MCP Server自体は認証認可のためにPATを利用するパターンとOAuthを利用するパターンがありますが、この実験では簡易なことを踏まえてPATを利用する方式を採用しています。OAuthを利用するパターンも対応自体はしているみたいです。

そうなると、まずはPATをAgent上で利用する方式について考える必要がありますが、ここではOpenAIが提供しているVaultという枠組みを利用します。 Vaultを利用すると、PATのような秘密値を直接Agentに渡すことなく、MCP接続のための認証情報を利用することができます。

Vault自体は現時点(2026-09-12)ではOpenAIのAPI Consoleから操作することができないので、API経由でcredentialの登録を行う必要があります。

今回は、次のようなコードによりVaultへのcredential登録を行いました。

type baseConfig struct {
	apiKey string
	model  string
}

type setupConfig struct {
	baseConfig
	githubPAT string
}

type vaultResult struct {
	vaultID      string
	credentialID string
}

func setupVault(ctx context.Context, client *openai.Client, cfg setupConfig) (vaultResult, error) {
	vault, err := client.Beta.Agents.Vaults.New(ctx, openai.BetaAgentVaultNewParams{
		Name: openai.String("GitHub MCP sandbox verification"),
		Metadata: map[string]string{
			"repository": defaultOwner + "/" + defaultRepo,
		},
	})
	if err != nil {
		return vaultResult{}, fmt.Errorf("create vault: %w", err)
	}

	credential, err := client.Beta.Agents.Vaults.Credentials.New(
		ctx,
		vault.ID,
		openai.BetaAgentVaultCredentialNewParams{
			Name: "GitHub PAT",
			Auth: openai.CredentialAuthCreateParamOfParamStaticBearer(
				githubMCPURL,
				cfg.githubPAT,
			),
		},
	)

	if err != nil {
		_, cleanupErr := client.Beta.Agents.Vaults.Delete(ctx, vault.ID)
		return vaultResult{}, errors.Join(
			fmt.Errorf("create GitHub credential: %w", err),
			cleanupError(cleanupErr),
		)
	}

	return vaultResult{vaultID: vault.ID, credentialID: credential.ID}, nil
}

このようなコードを実行すると、GitHub PATが登録されたVaultとcredentialのIDが返ってくるので、それを控えておきます。

OPENAI_VAULT_ID=vault_XXXX
OPENAI_CREDENTIAL_ID=credential_YYYY

Agentを動かしてみる

MCP Serverの利用準備が整ったので、実際にAgentを動かしてみます。 今回は以下のようなコードで動かしました。 (細かな定数名などについては適切に読み換えてください。)

type runConfig struct {
	baseConfig
	// vaultIDとcredentialIDは先ほど控えた値が入る想定
	vaultID      string
	credentialID string
	owner        string
	repo         string
}

func githubMCPTool(credentialID string) openai.AgentToolParamUnion {
	tool := openai.AgentToolParamMcp{
		ServerLabel: "github",
		Transport:   openai.McpTransportParamOfParamHTTP(githubMCPURL),
		AllowedTools: []string{
			"get_me",
			"search_issues",
			"issue_write",
			"issue_read",
		},
		Required:         openai.Bool(true),
		ConnectionOrigin: "service",
	}
	if credentialID != "" {
		tool.CredentialID = openai.String(credentialID)
	}

	return openai.AgentToolParamUnion{OfParamMcp: &tool}
}

func createIssuePrompt(owner, repo, verificationID string) string {
	return fmt.Sprintf(`%s/%sにテスト用Issueを1件作成してください。
タイトルには検証ID「%s」を含め、descriptionにはテストであることを記載してください。`,
		owner,
		repo,
		verificationID,
	)
}

func createIssue(
	ctx context.Context,
	client *openai.Client,
	cfg runConfig,
	verificationID string,
	out io.Writer,
) (sessionResult, error) {
	stream := client.Beta.Agents.Sessions.NewStreaming(ctx, openai.BetaAgentSessionNewParams{
		Agent: openai.BetaAgentSessionNewParamsAgent{
			Model:        openai.String(cfg.model),
			Instructions: openai.String("指定されたGitHubリポジトリだけを操作すること。"),
			Tools:        []openai.AgentToolParamUnion{githubMCPTool(cfg.credentialID)},
		},
		Environment: noEnvironment(),
		VaultIDs:    []string{cfg.vaultID},
		Input: openai.BetaAgentSessionNewParamsInputUnion{
			OfString: openai.String(createIssuePrompt(cfg.owner, cfg.repo, verificationID)),
		},
	})
	defer stream.Close()

	return consumeEvents(stream, out)
}

これを動かすと、想定通りGitHubの指定したリポジトリ上にIssueが作成されました。 非常に簡易的な実装にはなっていますが、それでもMCP Serverを絡めた一連の動きを実現できました。

なお、今回はtool useだけで閉じる内容となっており、それほど複雑なことをしていないので特に指定していませんが、shellやファイル操作を絡めたい場合にはOpenAI HostedやSelf Hostedな環境をEnvironmentとして指定してあげることで実現可能となっています。

まとめ

OpenAIのAgents APIという仕組みを触ってみました。

マネージドなOpenAIのAI AgentをAPI経由で利用できることが確認できて、自前管理するものが少ない点が嬉しいポイントだと思いました。

アプリケーション上にAgent系の機能を追加したりする場合には有力な選択肢になりそうです。