
AWS DevOps Agent に Lambda のタイムアウトを調査させて、修正プルリクエストまで作らせてみた
こんにちは、製造ビジネステクノロジー部の若槻です。
AWS DevOps Agent は障害を調査して根本原因を特定してくれますが、特定した原因を直すプルリクエストまで作らせられるのかが気になっていました。
そこで、意図的にタイムアウトする Lambda 関数を用意して、エージェントに「調査して修正プルリクエストを作って」と依頼してみました。
結論
- ネイティブの GitHub 連携をアクセスレベル「読み取りと書き込み」で登録していても、エージェントに渡る GitHub ツールは読み取り専用の 14 個だけでした。プルリクエストは作れません。これは連携が古いせいではなく仕様です
- 修正プルリクエストを作らせるには GitHub 公式のリモート MCP サーバー(
https://api.githubcopilot.com/mcp/)を別途接続する必要があります - MCP サーバーの認証は GitHub App の OAuth 3LO が使えます。OAuth App の
repoスコープより権限を絞れます - ただし OAuth 3LO の MCP サーバー登録は CloudFormation / AWS CDK では作成できません。IaC 化できるのは Association(ツール許可リスト)だけです
検証構成
Agent Space は既存のものを使い回しています。Agent Space 自体の作成は以下の記事で扱っています。
検証対象の Lambda 関数
ハンドラーの処理時間(10 秒)より短いタイムアウト値(3 秒)を設定して、意図的に Status: timeout を発生させます。
const PROCESSING_SECONDS = 10;
const sleep = (milliseconds: number): Promise<void> =>
new Promise((resolve) => setTimeout(resolve, milliseconds));
/**
* 長時間処理を模した検証用ハンドラー
*
* 関数のタイムアウト値より長く動作させることで、意図的に Task timed out を発生させる。
*/
export const handler = async (): Promise<void> => {
console.log(
`Start processing. This task takes ${PROCESSING_SECONDS} seconds.`,
);
await sleep(PROCESSING_SECONDS * 1000);
console.log("Finished processing.");
};
import * as cdk from "aws-cdk-lib";
import * as nodejs from "aws-cdk-lib/aws-lambda-nodejs";
import * as logs from "aws-cdk-lib/aws-logs";
import { Construct } from "constructs";
/**
* 検証用 Lambda 関数の実装
*
* ハンドラーの処理時間(10 秒)より短いタイムアウト値を設定することで、
* 意図的に Task timed out を発生させる。DevOps Agent にこの障害を調査させ、
* 修正プルリクエストを作成させるための検証用リソース。検証専用。
*/
export class SlowTaskFunctionConstruct extends Construct {
public readonly function: nodejs.NodejsFunction;
constructor(scope: Construct, id: string) {
super(scope, id);
const logGroup = new logs.LogGroup(this, "LogGroup", {
retention: logs.RetentionDays.ONE_WEEK,
removalPolicy: cdk.RemovalPolicy.DESTROY, // 検証用のため、スタック削除時に削除する
});
this.function = new nodejs.NodejsFunction(this, "Default", {
entry:
"lib/constructs/devops-agent-pr-verification/slow-task-function/function.ts",
handler: "handler",
timeout: cdk.Duration.seconds(3), // 処理時間より短く、意図的にタイムアウトさせる
logGroup,
});
}
}
デプロイして 5 回呼び出すと、すべてタイムアウトしました。
for i in 1 2 3 4 5; do
aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null \
--query '{StatusCode:StatusCode,FunctionError:FunctionError}' --output text
done
Unhandled 200
Unhandled 200
Unhandled 200
Unhandled 200
Unhandled 200
ログを見ると Duration: 3000.00 ms / Status: timeout です。
aws logs tail "$LOG_GROUP_NAME" --since 15m
INFO Start processing. This task takes 10 seconds.
END RequestId: fde2c844-72d9-4d28-8451-e3d0ebed9445
REPORT RequestId: fde2c844-72d9-4d28-8451-e3d0ebed9445 Duration: 3000.00 ms
Billed Duration: 3193 ms Memory Size: 128 MB Max Memory Used: 76 MB
Init Duration: 192.36 ms Status: timeout
なお Finished processing. は 1 度も出力されていません。処理が終わる前に強制終了されています。
検証 1:ネイティブの GitHub 連携だけで依頼する
まずは MCP サーバーを接続しない状態で依頼します。この Agent Space のネイティブ GitHub 連携は、マネジメントコンソールの 機能プロバイダー でアクセスレベルが 読み取りと書き込み と表示されています。

機能プロバイダーの登録一覧。GitHub は「読み取りと書き込み」だが、エージェントに渡るツールは読み取り専用だった(MCP Server は後から登録したもの)
エージェントに使えるツールを聞いてみました。
利用可能な GitHub 関連ツールの一覧を、ツール名と用途の表で正確に教えてください。
返ってきたのは 14 個で、すべて読み取り専用でした。
| ツール名 | 用途 |
|---|---|
get_github_file |
リポジトリ内の特定ファイルの内容を取得 |
get_github_pipeline_files |
.github/workflows/ 配下のワークフローファイルを取得・一覧表示 |
get_github_workflow_environments |
ワークフローの環境設定とデプロイ履歴を取得 |
get_github_workflow_run_logs |
特定のワークフロー実行の完全なログを取得 |
list_github_workflow_runs |
特定ワークフローの実行履歴一覧を取得 |
list_github_workflows |
リポジトリ内のすべてのワークフロー一覧を取得 |
list_repositories |
Agent Space に紐づくリポジトリの一覧を取得 |
git_log |
コミット履歴を取得 |
git_diff |
2 つの git リファレンス間の差分を表示 |
list_branches |
リポジトリのブランチ一覧を取得 |
repo_ls |
ディレクトリ構造をツリー形式で表示 |
repo_glob |
glob パターンでファイルを検索 |
repo_grep |
正規表現でコード内のパターンを検索 |
repo_read |
ファイルの内容を読み取り |
すべて読み取り専用です。書き込み操作(ブランチ作成・ファイル更新・PR作成など)は現在のツールセットには含まれていません。
この状態で調査と PR 作成を依頼しました。
Lambda 関数 DevOpsAgentPrVerification-SlowTaskFunction...(ap-northeast-1)がタイムアウトしています。CloudWatch Logs を確認して原因を特定し、この関数を定義している GitHub リポジトリ cm-rwakatsuki/security-infra のソースコードを調べて、根本原因を修正するプルリクエストを作成してください。
調査は完璧でした。CloudWatch Logs Insights でタイムアウトを確認し、GitHub のソースコードから該当箇所を特定しています。
| 項目 | 値 |
|---|---|
| Lambda タイムアウト設定 | 3 秒 |
| ハンドラーの処理時間 | 10 秒 |
| タイムアウト率(直近) | 100%(5/5 回) |
エージェントは修正すべきファイルと行まで言い当てました。
lib/constructs/devops-agent-pr-verification/slow-task-function/index.tslines 24-30
一方でプルリクエストは作れず、手動で作る手順を案内して終わりました。
GitHub への書き込み操作(ブランチ作成・ファイルコミット・PR作成)は、現在のエージェントの機能範囲外となっています。読み取り専用の GitHub ツールのみ利用可能です。
エージェントジャーナルで、この調査に使われたツールを確認します。
aws devops-agent list-journal-records \
--agent-space-id <agent-space-id> \
--execution-id <execution-id> \
--order ASC
呼ばれたツールは以下の通りで、書き込み系は 1 つもありません。
| ツール | 呼び出し回数 |
|---|---|
use_aws |
9 |
repo_read |
6 |
query_cloudwatch_logs |
5 |
repo_ls / gather_context / skill_read |
各 3 |
get_github_file / datetime |
各 2 |
repo_grep / git_log / list_associations |
各 1 |
コンソールに表示される「読み取りと書き込み」は GitHub App にインストールされている権限のことで、エージェントの調査チャットに渡されるツールセットとは別でした。ドキュメントの権限表を読むと、Contents: Read and write の Write は「エージェントが修正を提案する」ためと書かれています。
Contents | Read and write | Read repository source code for code review analysis and dependency mapping. Write access enables the agent to propose fixes for identified issues.
— Connecting GitHub
「連携が古いから」ではなかった
この Agent Space の GitHub 連携は少し前に設定したものだったので、「あとから追加された権限を承認していないだけではないか」と疑いました。ドキュメントにも次の注意書きがあります。
Until you accept a permission update, AWS DevOps Agent continues to operate with the previously granted permissions.
しかし、そうではありませんでした。
- GitHub App の権限は最新だった。
https://github.com/settings/installationsで AWS DevOps Agent のインストールを見ると、権限はRead access to metadataとRead and write access to actions, checks, code, commit statuses, issues, pull requests, and workflowsで、Permission updates requestedの表示もありません - 新しいチャットでも同じだった。別のチャットでツール定義を確認させても、組み込みツールは同じ 14 個で「ブランチ作成・ファイル書き込み・コミット・プルリクエスト作成ができるものは 1 つもありません」という回答でした
- そもそも設計がそうなっている。AWS の機能ページには、修正コードの実装は別のエージェントに任せる前提だと書かれています
AWS DevOps Agent also provides agent-ready instructions that can be implemented by another frontier agent
— Frontier agent – AWS DevOps Agent
DevOps Agent は「調査して修正指示(agent-ready instructions)を出す側」で、コードを書くのは Kiro のような別のエージェント、という役割分担です。GitHub App が書き込み権限を持っていても、調査チャットに書き込みツールが降りてこないのは仕様どおりということになります。
そして、その「別のエージェント」の代わりに GitHub MCP サーバーを直接持たせれば、DevOps Agent 自身に書かせられるというのが以降の話です。
GitHub MCP サーバーを接続する
AWS の Cloud Operations ブログでは、修正 PR を作らせるために GitHub 公式のリモート MCP サーバーを接続する構成が紹介されています。こちらは PAT(API キー認証)を使う手順ですが、今回は GitHub App を使った OAuth 3LO で接続しました。
認証方式の選択肢
aws devops-agent register-service --service mcpserver の authorizationConfig はタグ付きユニオンで、5 種類ありました。
oAuthClientCredentials | oAuth3LO | apiKey | bearerToken | authorizationDiscovery
一方 AWS::DevOpsAgent::Service が公開しているのは apiKey と oAuthClientCredentials だけです(aws-cdk-lib 2.257.0 で確認)。
| 認証方式 | AWS CLI | CloudFormation / CDK | 長期トークン |
|---|---|---|---|
apiKey |
✅ | ✅ | 必要(PAT) |
oAuthClientCredentials |
✅ | ✅ | 不要 |
oAuth3LO |
✅ | ❌ | 不要 |
bearerToken |
✅ | ❌ | 必要 |
authorizationDiscovery |
✅ | ❌ | 不要 |
oAuth3LO は returnToEndpoint に AWS コンソールのドメインを要求するため、実質ブラウザでの対話登録が前提です。IaC で完結させたいなら apiKey(PAT)、長期トークンを持ちたくないなら oAuth3LO というトレードオフになります。
今回は長期トークンを持ちたくなかったので oAuth3LO を選びました。
GitHub App を作成する
OAuth App ではなく GitHub App を使うと、repo スコープ(全リポジトリの read/write)ではなく App の permissions とインストール先リポジトリで権限を絞れます。GitHub App も Client ID / Client Secret を持ち、user access token を OAuth で発行できるので、3LO の設定にそのまま流用できます。
付与した permissions は 3 つだけです。
| 種別 | 権限 | アクセスレベル |
|---|---|---|
| Repository | Metadata | Read |
| Repository | Contents | Read and write |
| Repository | Pull requests | Read and write |
インストール先は Only select repositories で security-infra の 1 つに限定しました。Webhook は使わないので Active のチェックを外しています。

GitHub App のインストール設定。権限は 2 行だけで、対象リポジトリも 1 つに限定している
Callback URL には DevOps Agent のコントロールプレーンを指定します。この URL は MCP サーバー登録画面に表示されます。
https://api.prod.cp.aidevops.ap-northeast-1.api.aws/v1/register/mcpserver/callback
この登録は「GitHub が認可コードを渡してよい宛先」のホワイトリストです。登録しておかないと Authorize 画面にすら到達しません。実際の流れはこうなっていました。
- コンソールで登録を送信すると、DevOps Agent がブラウザを GitHub の認証 URL へリダイレクトする。このとき
redirect_uriに自分のコントロールプレーンを付ける
https://github.com/login/oauth/authorize
?response_type=code
&client_id=<client-id>
&state=<state>
&redirect_uri=https%3A%2F%2Fapi.prod.cp.aidevops.ap-northeast-1.api.aws%2Fv1%2Fregister%2Fmcpserver%2Fcallback
- GitHub が、受け取った
redirect_uriが App に登録済みの Callback URL と一致するかを検証する - 一致すれば Authorize 画面が出る。画面下部に
Authorizing will redirect to https://api.prod.cp.aidevops.ap-northeast-1.api.awsと表示される - 承認すると、GitHub がその URL へ
?code=...&state=...を付けてリダイレクトする - DevOps Agent のコントロールプレーンが認可コードを受け取り、交換 URL へクライアントシークレットと一緒に投げて user access token を取得する。この token が以降の MCP サーバー呼び出しの
Authorization: Bearerになる
redirect_uri を検証しない実装だと、攻撃者が宛先を書き換えたリンクを踏ませて認可コードを横取りできてしまいます。Callback URL の事前登録は、それを GitHub 側で塞ぐための仕組みです。
なお、API リファレンスの MCPServerOAuth3LOConfig には returnToEndpoint というフィールドがありますが、これは GitHub に登録する Callback URL とは別物なので注意が必要です。
| 何を指すか | 設定する場所 | |
|---|---|---|
Callback URL(redirect_uri) |
GitHub が認可コードを渡す先。DevOps Agent のコントロールプレーン | GitHub App 側 |
returnToEndpoint |
認可フロー完了後にブラウザを戻す先。AWS コンソールのドメインでなければならない | DevOps Agent 側(コンソールが自動で入れる) |
リージョンが URL に含まれる点も注意です。Agent Space が ap-northeast-1 なら ap-northeast-1 版が必要です。今回は最初どちらのリージョンが使われるか分からなかったので、GitHub App 側に 2 つとも登録しておきました。

GitHub App に登録した Callback URL。GitHub App は複数登録できる
結果として使われたのは Agent Space のリージョンと一致する ap-northeast-1 版だけでした。us-east-1 版は不要だったので削除できます。
MCP サーバーを登録する
マネジメントコンソールの 機能プロバイダー → MCP Server → Register から、4 ステップのウィザードで登録します。
| 項目 | 値 |
|---|---|
| 名前 | GitHubMcpServer |
| エンドポイント URL | https://api.githubcopilot.com/mcp/ |
| 認証フロー | OAuth 3LO |
| クライアント ID | GitHub App の Client ID |
| クライアントシークレット | GitHub App の Client secret |
| 交換 URL | https://github.com/login/oauth/access_token |
| 認証 URL | https://github.com/login/oauth/authorize |
| コードチャレンジサポート | オフ(GitHub は PKCE 非対応) |
| スコープ | 指定なし |
ステップ 1 では名前とエンドポイント URL を指定します。

ステップ 1。エンドポイントは GitHub 公式リモート MCP サーバーの URL を指定する
ステップ 2 で認証フローを選びます。コンソールの説明文は「3 種類」となっていますが、選択肢は 4 つ表示されました。

ステップ 2。今回は OAuth 3LO を選択した
ステップ 3 が認証設定です。GitHub App の場合、実際の権限は App の permissions で決まるためスコープの指定は不要でした。また PKCE は GitHub が非対応なので、コードチャレンジサポートはオフのままにします。
そしてこの画面の下部に、先に触れた Callback URL の案内が出ます。

ステップ 3。ユーザーガイドに記載のない「許可されたコールバック URL を設定する」の案内が、この画面にだけ表示される
送信すると GitHub の認可画面に飛び、承認すると登録が完了します。
CLI で確認すると authorizationMethod が oauth-3lo になっています。
aws devops-agent list-services --region ap-northeast-1
{
"serviceId": "<service-id>",
"serviceType": "mcpserver",
"name": "GitHubMcpServer",
"additionalServiceDetails": {
"mcpserver": {
"name": "GitHubMcpServer",
"endpoint": "https://api.githubcopilot.com/mcp/",
"authorizationMethod": "oauth-3lo",
"description": "GitHub の公式リモート MCP サーバー。修正プルリクエストの作成に使用する。"
}
}
}
ツール許可リストを AWS CDK で設定する
Service の登録はコンソール限定でしたが、Association(ツール許可リスト)は AWS::DevOpsAgent::Association で作成できます。PR 作成用の接続設定として最低限必要なソースコードはこれだけです。
import * as devopsagent from "aws-cdk-lib/aws-devopsagent";
import { Construct } from "constructs";
export interface GitHubMcpServerProps {
serviceId: string; // コンソールで OAuth 3LO 登録した GitHub MCP サーバーのサービス ID
tools: string[]; // Agent Space に許可する MCP ツール
}
interface GitHubMcpAssociationConstructProps {
agentSpaceId: string;
gitHubMcpServer: GitHubMcpServerProps;
}
/**
* GitHub MCP サーバーと Agent Space の関連付けの実装
*
* ネイティブの GitHub 連携が提供するツールは読み取り専用のため、修正プルリクエストを
* 作成させるには GitHub MCP サーバーを別途接続する必要がある。
* tools には MCP サーバーが公開しているツールのうち、この Agent Space に
* 許可するものだけを指定する(ツール許可リスト)。
* @see https://docs.aws.amazon.com/devopsagent/latest/userguide/configuring-integrations-and-knowledge-connecting-mcp-servers.html
*/
export class GitHubMcpAssociationConstruct extends Construct {
public readonly association: devopsagent.CfnAssociation;
constructor(
scope: Construct,
id: string,
props: GitHubMcpAssociationConstructProps,
) {
super(scope, id);
const { agentSpaceId, gitHubMcpServer } = props;
const { serviceId, tools } = gitHubMcpServer;
this.association = new devopsagent.CfnAssociation(this, "Default", {
agentSpaceId,
serviceId,
configuration: {
mcpServer: {
tools,
},
},
});
}
}
スタックはこれだけです。
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { AppParameter } from "../bin/parameter";
import { GitHubMcpAssociationConstruct } from "./constructs/devops-agent-pr-verification/github-mcp-association";
import { SlowTaskFunctionConstruct } from "./constructs/devops-agent-pr-verification/slow-task-function";
/**
* DevOps Agent の修正プルリクエスト作成検証用スタック
*
* 意図的にタイムアウトする Lambda 関数を作成し、DevOps Agent に調査と
* 修正プルリクエストの作成を行わせる。検証が終わったら cdk destroy で削除する。
*/
export class DevOpsAgentPrVerificationStack extends cdk.Stack {
constructor(
scope: Construct,
id: string,
props: AppParameter & cdk.StackProps,
) {
super(scope, id, props);
const { devOpsAgentPrVerification } = props;
const { agentSpaceId, gitHubMcpServer } = devOpsAgentPrVerification;
// 意図的にタイムアウトする Lambda 関数を作成
new SlowTaskFunctionConstruct(this, "SlowTaskFunction");
// GitHub MCP サーバーを Agent Space に関連付け(ツール許可リスト)
new GitHubMcpAssociationConstruct(this, "GitHubMcpAssociation", {
agentSpaceId,
gitHubMcpServer,
});
}
}
許可するツールを絞る
GitHub MCP サーバーが公開しているツールは 47 個ありました。merge_pull_request や delete_file のような危険なものも含まれます。
プルリクエストを作るのに必要な最低限は 4 つでした。
tools: [
"create_branch",
"create_or_update_file",
"create_pull_request",
"get_file_contents",
],
デプロイ後、CLI で許可リストを確認します。
aws devops-agent list-associations \
--agent-space-id <agent-space-id> --region ap-northeast-1
{
"associationId": "<association-id>",
"serviceId": "<service-id>",
"configuration": {
"mcpserver": {
"tools": [
"create_branch",
"create_or_update_file",
"create_pull_request",
"get_file_contents"
]
}
}
}
マネジメントコンソールの MCP サーバーツールを選択 画面でも、47 ツールのうち許可した分だけにチェックが入った状態になります。

MCP サーバーツールの選択画面。47 ツールのうち許可した 4 つだけがチェックされ、create_or_update_file や delete_file は外れている
検証 2:MCP サーバーを接続して依頼する
検証 1 とまったく同じ依頼を、新しいチャットで投げます。
Lambda 関数 DevOpsAgentPrVerification-SlowTaskFunction...(ap-northeast-1)がタイムアウトしています。CloudWatch Logs を確認して原因を特定し、この関数を定義している GitHub リポジトリ cm-rwakatsuki/security-infra のソースコードを調べて、根本原因を修正するプルリクエストを作成してください。ベースブランチは main です。
つまずいた点:create_or_update_file は日本語を壊す
最初の許可リストは get_file_contents / create_branch / create_or_update_file / create_pull_request の 4 つにしていました。この構成ではブランチ作成までは成功したものの、ファイルの更新で止まりました。
ジャーナルを見ると、MCP ツールは組み込みの invoke_user_tool 経由で、サーバー名がプレフィックスされた形で呼ばれています。
TOOL_USE invoke_user_tool input={"tool_name": "GitHubMcpServer_create_branch",
"arguments": {"owner": "cm-rwakatsuki", "repo": "security-infra",
"branch": "fix/slow-task-function-timeout", "from_branch": "main"}}
ブランチはこれで実際に作られました。続く create_or_update_file の呼び出しで問題が起きています。
TOOL_USE invoke_user_tool input={"tool_name": "GitHubMcpServer_create_or_update_file",
"arguments": "{\n \"owner\": \"cm-rwakatsuki\", ...
\"content\": \"aW1wb3J0ICogYXMgY2RrIGZyb20gImF3cy1jZGstbGliIjsK...
create_or_update_file は ファイル全体の内容を base64 で渡す 仕様です。この呼び出しには 2 つの問題がありました。
- 引数の JSON が途中で切れた。base64 が 443 文字で終わっており、
argumentsの文字列が未終端のままfinal_responseに遷移していました。ツール結果のレコードはジャーナルにも残っていません - 日本語が壊れた。切れた部分までをデコードすると、コメントがこうなっていました
/**
* 日試フリ Lambda 関数の定逤
*
* 遍nioi利用生日言言(ב 秂)(什失贚)を使意してえくっに
正しくは以下です。
/**
* 検証用 Lambda 関数の実装
*
* ハンドラーの処理時間(10 秒)より短いタイムアウト値を設定することで、
エージェントが自力で base64 エンコードするため、マルチバイト文字が化けています。「1 行だけ直したい」のにファイル全体を base64 で再生成させるのは相性が悪いということです。
push_files に差し替える
GitHub MCP サーバーには push_files という、プレーンテキストのまま複数ファイルをコミットできるツールがあります。base64 を経由しないので上記の問題を回避できます。
許可リストを差し替えました。
tools: [
"create_branch",
"create_pull_request",
"get_file_contents",
// create_or_update_file は content を base64 で渡す仕様でマルチバイト文字が
// 壊れるため、プレーンテキストで渡せる push_files を使わせる
"push_files",
],
AWS::DevOpsAgent::Service は更新不可でしたが、Association の Tools は Update requires: No interruption なので、許可リストは差分デプロイで切り替えられました。
npx cdk deploy DevOpsAgentPrVerification --context environment=dev
DevOpsAgentPrVerification | UPDATE_COMPLETE | AWS::DevOpsAgent::Association
✅ DevOpsAgentPrVerification
✨ Deployment time: 23.98s
プルリクエストが作られた
同じ依頼を投げ直したところ、調査からプルリクエスト作成まで完走しました。
プルリクエストの作成が完了しました! 🎉
呼ばれた MCP ツールは 3 つで、いずれも許可リストに入れたものだけです。
| MCP ツール | 結果 |
|---|---|
GitHubMcpServer_create_branch |
fix/slow-task-function-timeout を作成 |
GitHubMcpServer_push_files |
1 ファイル・1 行だけ変更してコミット |
GitHubMcpServer_create_pull_request |
プルリクエストを作成 |
この実行で呼ばれたツール全体はこうなりました。読み取り系のネイティブツールで調査し、書き込みだけ invoke_user_tool 経由で MCP に流れています。
| ツール | 呼び出し回数 |
|---|---|
query_cloudwatch_logs |
9 |
repo_read |
5 |
invoke_user_tool |
3 |
repo_ls / gather_context / skill_read / datetime |
各 2 |
use_aws / search_user_tools / repo_grep |
各 1 |
作られたプルリクエストを GitHub API で確認します。
curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.github+json" \
https://api.github.com/repos/cm-rwakatsuki/security-infra/pulls/102
number: 102
title: fix: SlowTaskFunction のタイムアウト値を 3 秒から 15 秒に延長
state: open | draft: False
head: fix/slow-task-function-timeout -> main
commits: 1 | changed_files: 1 | + 1 / - 1
差分は狙いどおり 1 行だけで、日本語コメントも壊れていません。
git diff origin/main..origin/fix/slow-task-function-timeout
--- a/lib/constructs/devops-agent-pr-verification/slow-task-function/index.ts
+++ b/lib/constructs/devops-agent-pr-verification/slow-task-function/index.ts
@@ -25,7 +25,7 @@ export class SlowTaskFunctionConstruct extends Construct {
entry:
"lib/constructs/devops-agent-pr-verification/slow-task-function/function.ts",
handler: "handler",
- timeout: cdk.Duration.seconds(3), // 処理時間より短く、意図的にタイムアウトさせる
+ timeout: cdk.Duration.seconds(15), // 処理時間より短く、意図的にタイムアウトさせる
logGroup,
});
}
PR の本文もエージェントが書いていて、根本原因の表と変更差分、影響範囲まで含まれていました。
根本原因
CloudWatch Logs を調査した結果、以下の不一致が判明しました。
項目 値 設定タイムアウト値 3 秒 実際の処理時間 ( PROCESSING_SECONDS)10 秒
なお、コメントの文言(「処理時間より短く、意図的にタイムアウトさせる」)は変更後の値と矛盾したまま残っています。「タイムアウト値の行だけを変更してください」と指示したためですが、コードの意図を表すコメントの追従までは面倒を見てくれませんでした。
GitHub 側には App 経由と記録される
GitHub の PR 画面を見ると、コメントの署名が with devops-agent-github-mcp-... となっています。OAuth 3LO で発行された user access token は「ユーザーとして、この GitHub App 経由で」という扱いなので、誰の代理でどのアプリが操作したかが GitHub 側に残ります。

エージェントが作成したプルリクエスト。コメントの署名に「with (GitHub App 名)」が付き、差分は +1 -1 の 1 行のみ
検証結果まとめ
| # | 確認したこと | 結果 |
|---|---|---|
| 1 | ネイティブ GitHub 連携だけで PR を作れるか | ❌ アクセスレベルが「読み取りと書き込み」でも、渡されるツールは読み取り専用 14 個 |
| 1' | それは連携が古いせいか | ❌ GitHub App の権限は最新(保留中の更新なし)。別チャットでも同結果。設計どおり |
| 2 | 調査そのものの精度 | ✅ タイムアウト率 100%(5/5)を突き止め、修正すべきファイルと行まで特定 |
| 3 | GitHub MCP サーバーを OAuth 3LO で登録できるか | ✅ GitHub App の Client ID / Secret で登録でき、長期トークン不要 |
| 4 | MCP サーバー登録を IaC 化できるか | ❌ OAuth 3LO は CloudFormation / CDK 非対応(apiKey / oAuthClientCredentials のみ) |
| 5 | ツール許可リストを IaC 化できるか | ✅ AWS::DevOpsAgent::Association で可能。Tools は差分デプロイで変更できる |
| 6 | MCP 経由で PR を作れるか | ✅ create_branch → push_files → create_pull_request で完走 |
| 7 | create_or_update_file は使えるか |
⚠️ base64 でファイル全体を渡す仕様。引数が途中で切れ、日本語も壊れた |
片付けについて
検証が終わったら、以下を消しておくのが良さそうです。
- エージェントが作ったプルリクエストとブランチ
- 検証用スタック(
npx cdk destroy DevOpsAgentPrVerification) - GitHub MCP サーバーのアカウントレベル登録(Association を外してから 機能プロバイダー → アクション → 登録解除)
- GitHub App(インストールを削除し、App 自体も削除)
特に GitHub App は Contents: Read and write を持ったまま残るので、使わないなら消しておくべきです。App のインストールを消せば、MCP サーバー側にトークンが残っていても書き込みはできなくなります。
おわりに
「DevOps Agent は調査だけでなく修正プルリクエストまで作れるのか」を確かめてみました。答えは 「作れるが、ネイティブの GitHub 連携だけでは無理で、GitHub MCP サーバーの接続が必要」 でした。
ネイティブ連携のアクセスレベルが「読み取りと書き込み」と表示されていても、調査チャットに渡るツールは読み取り専用です。ここは表示から素直に推測できず、実際にエージェントにツール一覧を聞いてみるまで分かりませんでした。
最初は「連携を設定したのが古いせいかもしれない」と疑ったのですが、GitHub App の権限は最新で保留中の更新もなく、これは仕様でした。AWS の機能ページを読み直すと、DevOps Agent は修正の指示(agent-ready instructions)までを担当し、実装は Kiro のような別のエージェントに渡す設計になっています。今回やったのは、その「別のエージェント」の役割を GitHub MCP サーバーで肩代わりさせることだったと言えます。
権限設計の観点では、GitHub App + OAuth 3LO は良い落としどころだと思います。長期の PAT を持たずに済み、GitHub App の permissions とインストール先リポジトリで二重に絞れて、GitHub 側にもアプリ名が残ります。その代わり Service の登録は IaC 化できないので、「Service 登録はコンソールで一度だけ、ツール許可リストは CDK で管理」 という分担になります。
ツール許可リストの選定は思ったより効きました。47 ツールのうち 4 つに絞ることで merge_pull_request や delete_file を最初から遮断できます。エージェントに書き込み権限を渡すときは、ここを最小にしておくのが効果的だと感じました。
以上






