はじめに
RAG のナレッジベースを運用していると、地味に面倒なのが同期です。
S3 にファイルを置き直した、Confluence のページを直した、そのたびに「同期」を手で叩かないと、エージェントは古い情報のまま答え続けます。
これを自動化しようとすると、これまでは EventBridge などで自前のスケジューラを組む必要がありました。
2026 年 9 月 4 日、Amazon Bedrock のマネージドナレッジベースに、日次・週次・月次の同期スケジュールが入りました。
自動同期スケジュール
マネージドナレッジベースに、今回スケジュール同期が付きました。指定できるのは 4 つです。
ポイントは 実行時刻を選べない ことです。「毎週月曜」までは指定できますが、その日の何時に走るかは AWS 側が決めます(日次についてはオフピーク時間と明記されています)。cron 式のような細かい指定はできません。
同期は差分のみで、前回から追加・変更・削除されたものだけを処理します。スケジュールを入れたあとも手動同期はいつでも叩けます。
やってみた
東京リージョンで、S3 に置いたテキスト 1 本をソースにして組み立てます。一式を GitHub に置いたので、clone してそのまま動かせます。
git clone https://github.com/leomaro7/bedrock-managed-kb-sync-schedule.git
cd bedrock-managed-kb-sync-schedule
terraform init
terraform apply
これで作られるのがこの構成です。
ここまでは従来のマネージドナレッジベースの作成と同じですので詳しい説明は省きます。
なお、マネージドナレッジベースについては過去に以下の記事も書いてますので、よければ参考にしてください。
syncSchedule の後乗せ(sync_schedule.tf)
ここが本題です。syncSchedule は aws_bedrockagent_data_source に引数が存在せず、CloudFormation のリソーススキーマにも入っていないため、awscc や Cloud Control API 経由でも書けません。API と AWS CLI にだけある状態です。
そこで terraform_data の local-exec から update-data-source を叩きます。
resource "terraform_data" "sync_schedule" {
triggers_replace = {
data_source_id = aws_bedrockagent_data_source.s3.data_source_id
configuration = jsonencode(local.data_source_configuration_with_schedule)
}
lifecycle {
replace_triggered_by = [aws_bedrockagent_data_source.s3]
}
provisioner "local-exec" {
interpreter = ["/bin/bash", "-c"]
environment = {
DS_DESC = aws_bedrockagent_data_source.s3.description == null ? "" : aws_bedrockagent_data_source.s3.description
DS_POLICY = aws_bedrockagent_data_source.s3.data_deletion_policy
DS_CONFIG = jsonencode(local.data_source_configuration_with_schedule)
# KB_ID / DS_ID / DS_NAME / AWS_REGION も同様に渡す
}
command = <<-EOT
set -euo pipefail
args=(
--region "$AWS_REGION"
--knowledge-base-id "$KB_ID"
--data-source-id "$DS_ID"
--name "$DS_NAME"
--data-deletion-policy "$DS_POLICY"
--data-source-configuration "$DS_CONFIG"
)
if [[ -n "$DS_DESC" ]]; then
args+=(--description "$DS_DESC")
fi
aws bedrock-agent update-data-source "$${args[@]}"
EOT
}
}
送り込む syncSchedule は tagged union(daily / weekly / monthly のどれか 1 つだけを書く形式)で、sync_schedule 変数に渡します。
切り替えるときは apply し直すだけです。
terraform apply -var='sync_schedule={weekly={dayOfWeek="MONDAY"}}'
terraform apply -var='sync_schedule={daily={}}'
terraform apply -var='sync_schedule={monthly={dayOfMonth={dayNumber=15}}}'
terraform apply -var='sync_schedule={monthly={dayOfMonth={lastDayOfMonth={}}}}'
結果確認
リポジトリの verify.sh が、実機の状態を読むだけのスクリプトです。
./verify.sh
{ "weekly": { "dayOfWeek": "MONDAY" } }
コンソールにも反映されます。
月末指定に切り替えると、こうなります。
手動同期も走らせてみたところ、テキスト 1 本が問題なくインデックスされました。スケジュール実行分も手動実行分も、この同期履歴に並びます。
確認が済んだら片付けます。
terraform destroy
注意点: Terraform 側の更新だけでスケジュールが消える
UpdateDataSource は dataSourceConfiguration を 全置換 します。
description を足しただけの in-place 更新でも、Provider は syncSchedule を知らないので送らず、On-demand に戻ります。
terraform_data に replace_triggered_by を付けておくと、消えても自動で入り直ります。
ただし自動で戻るのは Terraform 自身がデータソースを更新したときだけです。
コンソールから変えられた場合は、Terraform が syncSchedule を管理していない以上それを差分と見なせないので、手動で流し直すことになります。




