Agents for Amazon Bedrockを使ってBacklogの課題とWikiを検索する

# はじめに

前回の記事｢Bedrockを使って、S3に置いた独自データに応答してくれるチャットボットを作ってみた。｣では､Knowledge Bases for Amazon BedrockとAgents for Amazon Bedrock､Pineconeを使用してS3バケット配置したオブジェクトを対象としたRAGを構築しました｡

https://qiita.com/revsystem/items/55a4c2ee25ca10964102

本記事では､Agents for Amazon BedrockのAction groupsを使用し､自然言語でBacklogの課題やWikiを検索するチャットボットを作成します｡

今回は､AgentsがBacklog APIを使用して課題やWikiをキーワード検索し､その結果をもとにAgentsが回答を組み立てます｡RAGではないので､キーワードに対して類似度の高いものを検索するようなことはできません｡検索の精度や結果はBacklog APIに異存します｡そのため､Backlogの検索にAgents for Amazon Bedrockが向いているかはさておき､Action groupsの構築方法や運用の理解を深めることに重点を置きました｡

# デモ画面

`契約について検索してください`というメンションに対して､`契約`というキーワードでBacklogの課題とWikiを検索し､その結果をSlackに返しています。Backlogの課題はプロジェクトをまたいで検索できますが、Wikiはプロジェクトキーを指定して検索する必要があります。そのため、チャットボットはプロジェクトキーを問う返信を行います。検索結果には、課題の検索結果が10件とWikiの検索結果が3件表示されています。この画面は、最も期待どおりに動作した例です。毎回、課題とWikiの検索結果が得られるわけではありませんでした。
また、このデモ画面内には`福島`という名称が含まれていますが、Wikiに記述している名称は別のものです。同様に、`鈴木建設`や`鈴木様`､`池田様`もWikiに書かれている内容とは異なります。Agentsが回答を作成する際に勝手に情報を書き換えたようです。この点はプロンプトで制御できるのかもしれません｡


![デモ画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/7e55bf84-24c3-8a54-c427-0bdf48e49bf9.png)

# 構成図

![構成図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/0b13cfed-3a12-9b02-d5e8-ecae689b9190.png)

# 参考情報

https://docs.aws.amazon.com/code-library/latest/ug/bedrock-agent-runtime_example_bedrock-agent-runtime_InvokeAgent_section.html

https://aws.amazon.com/jp/blogs/news/preview-enable-foundation-models-to-complete-tasks-with-agents-for-amazon-bedrock/

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/agents-create.html#agents-action-lambda-old

https://docs.aws.amazon.com/bedrock/latest/userguide/agents-api-schema.html

https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html#ps-integration-lambda-extensions-add

https://developer.nulab.com/ja/docs/backlog/#

https://swagger.io/specification/

https://github.com/keithrozario/Klayers

https://iret.media/75940

https://zenn.dev/beijaflor/articles/3d554e51bb20c6

https://qiita.com/Kalmari/items/bf07b8345054f4af605e

https://qiita.com/cyberBOSE/items/e8c2d0207d03b6934a1c

https://qiita.com/kazuneet/items/36f6d42fecbad0469d35

# 環境構築

- 以下のリソースを作成･削除･変更できる権限をもつAWSユーザーを利用すること
  - AWS IAM
  - AWS Lambda
  - AWS CloudFormation
  - AWS Secrets Manager
  - Amazon API Gateway
  - Amazon S3
  - Amazon CloudWatch Logs
  - Amazon Bedrock
- 使用するAWSリージョンは、us-east-1
- Slack Appを作成するためのアカウントや権限を持っている

## 開発環境構築

### 作業環境のOSバージョン

Windows 11上のWSLでUbuntu 23.04を動かしています。

```console
$ cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Ubuntu 23.04"
```

### Python環境

```console
$ python3 --version
Python 3.12.0
```

```console
$ python3 -m venv .venv
source .venv/bin/activate
```

```console
$ pip3 install --upgrade pip
$ pip3 --version
pip 24 from /home/xxx/.venv/lib/python3.12/site-packages/pip (python 3.12)
```

### AWS環境構築

aws configureコマンドでデフォルトのリージョンやクレデンシャルを設定するか､もしくは~/.aws/configや~/.aws/credentialsを用意します。

#### AWS SAM CLIインストール

AWS上でサーバーレスアプリケーションを構築､実行するAWS SAMを使用します｡

[Installing the AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) の手順に従い、AWS SAM CLIをインストールします。今回はx86_64環境でLinux OSを使用するため、x86_64 - command line installerの手順を実行します｡

```console
$ sam --version
SAM CLI, version 1.108.0
```

version 1.104.0 ~ 1.106.0では[ビルド時に不必要なWarningメッセージが出力される](https://github.com/aws/aws-sam-cli/issues/6444)ため修正パッチが適用された1.107.0以降を使用します。
この件は以下のissueで解決しています｡

https://github.com/aws/aws-sam-cli/issues/6444

### Slack Appの作成

[Slac API](https://api.slack.com/apps?new_app=1)を開き､From scratchからSlack Appを作成します｡ここでは、App Nameを`aws-sam-bedrock-action-group`とします｡

Basic Information画面のApp Credentialsに表示されているSigning Secretは`SlackSigningSecret`として次のSecret Managerのシークレット登録に使用します。

![App Credentials](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/dcdec7e0-a9f6-6109-8e01-b4798c9716ab.png)

OAuth & Permissions画面のOAuth Tokens for Your WorkspaceにあるBot User OAuth Tokenは、`SlackBotToken`として次のSecret Managerのシークレット登録に使用します。

![OAuth Tokens for Your Workspace](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/7d19fb7c-908b-4c6b-ce5a-5ccfe807da7d.png)

OAuth & Permissions画面のBot Token Scopesに`app_mentions:read`と`chat:write`を追加します｡

![Bot Token Scopes](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/ac765a8c-ac58-17f4-f370-a1e24ca8fb85.png)

### Slackシークレット情報をSecret Managerに登録

あらたにシークレットを作成し、ここまでの手順で作成した以下のシークレット情報を登録します。シークレット名は、`Bedrock-sam-secrets-action-group`とします。このシークレット名は後述のtemplate.yaml内のSECRET_NAMEに定義しているため、異なるシークレット名を使用する場合はtemplate.yaml内のSECRET_NAMEも変更します。

|シークレットキー|値|
|-- |-- |
|SlackSigningSecret|前項のSlackのSigning Secret|
|SlackBotToken|前項のSlackのBot User OAuth Token|

![シークレット作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/7ff359c7-de79-ab82-e3ed-1c9299a119ab.png)

### アプリケーションの構築

ディレクトリ構造は以下のとおりです｡

```console
.
├── README.md
├── assets
│   ├── backlogSearch.json
│   └── backlogSearch.yml
├── backlogSearch
│   ├── __init__.py
│   └── app.py
├── bedrock_action_group_slack_app
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
├── samconfig.toml
└── template.yaml
```

上記のソースコード類はGitHubリポジトリにアップロードしています｡

https://github.com/revsystem/aws-sam-bedrock-action-group-slack-app

#### assets/backlogSearch.yml, assets/backlogSearch.jsonの構成

assets/backlogSearch.ymlもしくはassets/backlogSearch.jsonは､Backlogの課題やWikiを検索するためのOpenAPIスキーマです｡これらを**任意のS3バケットに配置**します。後述のAction groupsの設定で使用します。
OpenAPIスキーマは､[Backlog API とは](https://developer.nulab.com/ja/docs/backlog/#)で公開されているAPI仕様をもとに作成しました｡ほぼ､GitHub Copilotが生成してくれたものを使用しています｡

https://twitter.com/revsystem/status/1751269635641741630

`__init__.py`は空のファイルです｡
bedrock_action_group_slack_app/requirements.txtは以下のとおりです｡boto3やrequestsも必要ですが､それらはLambdaレイヤーで追加するようtemplate.yamlに記述します｡

```console
slack-bolt
slack-sdk
```

#### template.yamlの構成

AWS SAM テンプレートファイル(template.yaml)に､作成するAWSリソースを定義します｡
ここでは､ふたつのLambda関数を作成します｡ひとつはSlack Event Subscriptionsを受け取り､もうひとつはBacklogの課題やWikiを検索するための関数です｡それぞれ､Lambda関数用ロールやポリシー､Lambdaの環境変数などを記述します｡その他に､以下のレイヤーやリソースベースポリシーが含まれます｡

- Lambda関数からSecrets Managerにアクセスするための`AWS-Parameters-and-Secrets-Lambda-Extension`レイヤー
- Lambda関数内からimportするためのboto3やrequestsをパッケージにしたレイヤー
- BedrockkからLambda関数を扱うためのリソースベースポリシー

`AWS-Parameters-and-Secrets-Lambda-Extension`レイヤーのARNは[Using Parameter Store parameters in AWS Lambda functions](https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html#ps-integration-lambda-extensions-add)のドキュメントにリージョンやアーキテクチャ毎に掲載されています｡
boto3やrequestsのレイヤーは､[keithrozario/Klayers](https://github.com/keithrozario/Klayers?tab=readme-ov-file#list-of-arns)のリポジトリにある`List of ARNs`に､Pythonバージョンとアーキテクチャ毎に掲載されています｡今回は､Python 3.12, arm64を使用するので､[Layers for Python 3.12-arm64](https://github.com/keithrozario/Klayers/tree/master/deployments/python3.12-arm64)の一覧からus-east-1用のARNを使用します｡

Lambdaレイヤーは以下のようにtemplate.yamlに記述しています｡

```yaml
      Layers:
        # Layer for AWS Parameter Store and Secrets Manager
        - arn:aws:lambda:us-east-1:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension-Arm64:11
        # Layer for requests and boto3
        - arn:aws:lambda:us-east-1:770693421928:layer:Klayers-p312-arm64-requests:1
        - arn:aws:lambda:us-east-1:770693421928:layer:Klayers-p312-arm64-boto3:1
```

適用すると､Lambda関数のLayersに以下のように表示されます｡

![Lambdaレイヤー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/6bdd1573-e396-a166-f516-2df8afb9d531.png)

リソースベースポリシーは､以下のようにtemplate.yamlに記述しています｡

```yaml
  BacklogSearchFunction:
    Type: AWS::Serverless::Function
    Properties:

(途中省略)

  # Resouse based policy for lambda.
  PermissionForBacklogSearchToInvokeLambda:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !GetAtt BacklogSearchFunction.Arn
      Action: lambda:InvokeFunction
      Principal: bedrock.amazonaws.com
```

適用すると､Lambda関数の設定のResource-based policy statementsに以下のように表示されます｡

![リソースベースのポリシー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/eb13d5f8-a197-cc7c-f86e-f0134e367af7.png)

template.yaml内のEnvironmentにある`SECRET_NAME`と`REGION_NAME`には､それぞれ先ほど作成したSecrets Managerのシークレットの名前とリージョンを設定します｡

Lambda関数の実行ロール内のポリシーでは`Resource: "*"`としていますが、本番環境などでは許可するリソースを特定したほうがよいでしょう。例えば、AgentsのResourceを特定する場合は以下のように指定します。

```text
Resource: "arn:aws:bedrock:{Region}:{AWS Account ID}:agent-alias/{Agents ID}/{Agents Alias}"
```

#### samconfig.tomlの構成

SAM CLIの実行設定ファイル(samconfig.toml)に､SAM CLIを実行する際の設定を定義します｡AWS SAMのチュートリアル: Hello World アプリケーションのデプロイを実行した際に作成されるsamconfig.tomlをもとにしています｡今回の例では､以下の点を変更しています｡

- `[default.global.parameters]`セクションのstack_nameを"sam-app"から"bedrock-slack-rag-appt"に変更
- `[default.deploy.parameters]`セクションにregion指定を追加
- `[default.deploy.parameters]`セクションのcapabilitiesを"CAPABILITY_IAM"から"CAPABILITY_NAMED_IAM"に変更

#### bedrock_action_group_slack_app/app.pyの構成

bedrock_action_group_slack_app/app.pyは､Slack Event Subscriptionsを受け取り､Slackのメンションイベントに応答するための関数です｡boto3クライアントを使用してAgentsのinvoke_agentメソッドを呼び出し､Agentsにメッセージを送信します｡そして､レスポンスをSlackに返します｡

```python
    client = boto3.client(
        service_name='bedrock-agent-runtime',
        region_name="us-east-1",
        config=Config(
            read_timeout=180,
        )
    )

    response = client.invoke_agent(
        inputText=prompt,
        agentId=agent_id,
        agentAliasId=agent_alias_id,
        sessionId=session_id,
        enableTrace=enable_trace,
    )
```

#### backlogSearch/app.pyの構成

backlogSearch/app.pyは､Agentsからイベントデータを受け取り､Backlogの課題やWikiを検索するための関数です｡
event["apiPath"]が'/issues'の場合は課題を検索し､'/wikis'の場合はWikiを検索します｡このapiPathは､AgentsのAction groupsの設定で読み込むOpenAPIスキーマのpathsに記述されています｡それぞれの関数の結果をAgentsの形式に合わせて返します｡

```python
    if api_path == "/issues":
        body = issue_search(parameters)

    elif api_path == "/wikis":
        body = wiki_search(parameters)

    response_body = {"application/json": {"body": json.dumps(body)}}

    action_response = {
        "actionGroup": event["actionGroup"],
        "apiPath": event["apiPath"],
        "httpMethod": event["httpMethod"],
        "httpStatusCode": 200,
        "responseBody": response_body,
    }
    api_response = {"messageVersion": "1.0", "response": action_response}
    return api_response
```

課題検索を行うissue_search関数では､レスポンスボディの中から課題キー､課題の件名､課題の状態､担当者､期限日を返します｡全ての情報を返そうとすると検索結果の件数や課題本文のサイズなどで`Lambda response exceeds maximum size 25KB`のエラーが発生するため返す情報を絞っています｡

Wiki検索を行うWiki_serach関数では､レスポンスボディの中からWiki名と本文の先頭100文字を返します｡これも同様にエラーを回避するために情報を絞っています｡

### ビルド

template.yamlがあるディレクトリで､ビルドコマンドを実行します｡

```console
sam build
```

ビルドに成功すると､以下のようなメッセージが表示されます｡

```console
Starting Build use cache
Building codeuri: /home/xxx/aws-sam-bedrock-action-group-slack-app/backlogSearch runtime: python3.12
metadata: {} architecture: arm64 functions: BacklogSearchFunction
Manifest is not changed for (BedrockAssitantFunction), running incremental build
Building codeuri: /home/xxx/aws-sam-bedrock-action-group-slack-app/bedrock_action_group_slack_app
runtime: python3.12 metadata: {} architecture: arm64 functions: BedrockAssitantFunction
requirements.txt file not found. Continuing the build without dependencies.
 Running PythonPipBuilder:CopySource
 Running PythonPipBuilder:CopySource
 Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
```

### デプロイ

ビルドでエラーがなければsam deployコマンドを実行し､デプロイを行います。

```console
sam deploy
```

デプロイが成功すると､CloudFormationがチェンジセットを実行する様子とともに以下のような情報がコンソールに出力されます｡

```console
CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------
Key                 BacklogSearchFunction
Description         Backlog Search Lambda Function ARN
Value               arn:aws:lambda:us-east-1:xxxxxxxxxxxx:function:bedrock-action-group-slack-a-BacklogSearchFunction-xxxxxxxxxxxx

Key                 BedrockAssitantApi
Description         The URL of Slack Event Subscriptions
Value               https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/slack/events

Key                 BedrockAssitantFunction
Description         Bedrock Assistant Lambda Function ARN
Value               arn:aws:lambda:us-east-1:xxxxxxxxxxxx:function:bedrock-action-group-slack-BedrockAssitantFunction-xxxxxxxxxxxx

Key                 BedrockAssitantFunctionIamRole
Description         Implicit IAM Role created for Bedrock Assistant function
Value               arn:aws:iam::xxxxxxxxxxxx:role/bedrock-action-group-slack-app-lambda-role
----------------------------------------------------------------------------------------------------------------------------------
```

### Slack Appの設定

メンションイベントに応答するために､Event Subscriptions画面のSubscribe to bot eventsにapp_mentionを追加します｡

![Event Subscriptions](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/27e712e6-9106-66cc-b28c-cc8158f88e01.png)

Event Subscriptions画面のEnable EventsをOnにし､Request URLにデプロイ時に出力されたURL https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/slack/events を入力します｡
`Verified ✓` と表示されれば､正しいURLが入力されています｡レスポンスが得られるようになるまで時間がかかる場合があります。正しいURLを入力しているにもかかわらずVerifiedとならない場合は、時間をおいて再試行します。

![Enable_events.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/d0daeada-23c8-c170-0898-6672773f9717.png)

設定を追加後､画面最下部にあるSave Changesをクリックし内容を保存します｡

### Slack Workspaseにアプリをインストール

Install App画面のInstall to Workspaceをクリックし､Slack AppをWorkspaceにインストールします｡
インストールに成功すると､Thank you!画面が表示されます｡Slackアプリをインストールしている場合は`click here`のリンク､Webブラウザを使用している場合は､`this link`をクリックしてSlackを開きます｡

## Bedrock環境構築

### Agentsの設定

[Agents](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/agents/create)を開き､Agentを作成します｡

|入力/選択項目|内容|
|-- |-- |
|Agent name|任意のAgents名|
|Agent description|Agentsの説明文|
|User Input| Yes |
|IAM Permissins| 新規にロールを作成する場合は､Create and use a new service role｡既存のロールを利用する場合は Use an existing service role |
|Idle session timeout| 30 Minutes |

![Agent作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/f7ea9074-92ca-31e3-b690-dd09153a39b3.png)

"User Input" は､Agentsが回答するための十分な情報がない場合に､ユーザーに追加の情報を求めることができるかを選択します｡Yes,Noのどちらを選択しても良いのですが､Yesのほうが会話らしくなると思います｡
"Idle session timeout"は､入力が何もない状態でセッションを維持する時間｡セッションが有効な間であれば､以前の会話履歴を引き継いで会話を続けることができます｡

Agentsが使用する言語モデルを選択します｡記事執筆時点では､Anthropic社の"Claude instant V1","Claude instant V2", "Claude instant V2.1"のみが選択可能です｡

![Agentsの言語モデルを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/d8557954-3478-372a-4f5d-7c1b88e29783.png)

`Instructions for the Agent`には､エージェントが実行するタスクについて明確かつ具体的な指示を入力します｡

ここでのポイントは､Agentsがタスクを実行する順番や実行するLambda関数の理解を深めるために具体的な指示を与えることです｡例えば､ Agentsは実行するLambda関数に個々のクエリパラメータを処理する実装を見つけられない場合に"依頼内容を実現する実装がない"と判断し処理を中断することがありました｡そのため､ それを防ぐ指示を含めます｡また､依頼内容に対してOpenAPIスキーマのどのパスを使用するかを指示することで､Agentsが適切な処理を行う助けになるようです｡ただし､この指示は40~1,200文字以内という制限があります｡

上記のポイントや指示を踏まえて､以下のような指示を入力します｡
指示内にあるGET::backlogSearch::getIssueListやGET::backlogSearch::getWikiListの`backlogSearch`は､Action groupsの設定名です｡`getIssueList`や`getWikiList`は､OpenAPIスキーマのpathsに記述されているoperationIdです｡

上記のポイントや以下の指示は､Agentsの反応を試す中で経験的に得たものです｡おおよそ期待した結果が得られたので､おそらく考え方は合っていると思います｡

```text
あなたはBacklogの課題やWikiを検索するするプロフェッショナルです。
以下の手順でデータを検索してください。一度にすべてを行ってはいけません。user::askuser を通じて1つずつ実行してください。

1. 私の依頼内容を正しく理解してください。例えば、私が"点検に関する課題を10件探し、件名の昇順で一覧にしてください。"と依頼した場合、検索キーワード=点検, 課題を取得する件数=10, 並び替えに使用する属性=件名, 並び順=昇順 のように依頼内容を適切に分解してください。
2. あなたは依頼内容に基づいてfunctionを実行します。functionのコードを参照してfunctionが依頼内容を処理可能か否かを推論する場合、コードの内のコメントも参照しコードの仕様を理解する必要があります。例えば、コード内に個々のクエリパラメータを処理する実装がない場合でも短絡的に"依頼内容を実現する実装がない"と判断してはいけません。クエリパラメータを辞書形式のリストで受け取って値を処理している可能性があります。functionがクエリパラメータをどのように処理しているか仕様がコメントに書かれているので、コメントも参照しfunctionの仕様を理解してください。
3. 与えられたAPIスキーマを正しく理解してください。そのうえで、分解した依頼内容をAPIスキーマをもとにパラメータに当てはめます。例えば、「1. 私の依頼内容の理解」で与えられた依頼内容の例の場合は、GET::backlogSearch::getIssueListに対してはkeyword=点検, count=10, sort=件名(summary), order=asc のようにパラメータに値を当てはめます。GET::backlogSearch::getWikiListに対しては、keyword=点検を当てはめます。
4. 私の依頼に対して、はじめに GET::backlogSearch::getIssueListを実行し続けてGET::backlogSearch::getWikiList実行します。それぞれの結果を提示してください｡GET::backlogSearch::getIssueListの結果は､`課題キー`, `課題名`, `課題のステータス`, `担当者`, `期日`のみ提示してください。課題の期日が未設定の場合は､'なし'と回答します｡GET::backlogSearch::getWikiListの結果は、Wiki名とWikiの内容を提示してください。

出力例:

    ```
検索結果
{課題キー}, {課題名}, {課題のステータス}, {担当者}. {期日}

Wikiの検索結果
{Wiki名}, {Wikiの内容}
    ```
```

続いて､Action groupsの設定を行います｡ここで先ほどデプロイしたLambda関数や､OpenAPIスキーマを設定します｡
assets/backlogSearch.jsonもしくはassets/backlogSearch.yamlを任意のS3バケットにアップロードし､そのオブジェクトパスをS3 Urlに設定します｡

|入力/選択項目|内容|
|-- |-- |
|Action group name|任意のAction groups名｡先ほどの指示内容に合わせて`backlogSearch`とします｡|
|Description|Action groupsの説明文|
|Select Lambda function|先ほどデプロイしたLambda関数のうち､名前に`BacklogSearchFunction`が含まれる関数を選択｡|
|S3 Url|S3バケット内にあるbacklogSearch.yamlかbacklogSearch.jsonのオブジェクトパス|

![Action groupsの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/657c58e5-c946-2258-5c2d-b97700b59a7b.png)

今回はknowledge baseは使用しないので､何も入力せず次に進みます｡

![knowledge baseの設定はスキップ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/47f8b895-9f7f-1ab1-8003-359c69b0e267.png)

Agentsの設定が完了すると､概要がこのように表示されます｡APIからAgentsを呼び出す際に`ID`を使用します｡ **AgentsのIDは後述のSecret Managerのシークレット登録に使用します。**
右上のEditからAgentsの設定を変更することができます｡

![Agentsの設定概要](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/0f00d188-925a-8cf1-fca8-aab3725bd673.png)

### Agents エイリアスの作成

AgentsをAPIから呼び出す際は､Agents本体ではなくエイリアスを使用します｡そこで､Agentsに対するエイリアスを作成します｡
右上のCreateから新規作成画面に進みます｡

![Agents エイリアスの作](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/56917617-5697-c855-2de5-b1ad730d7620.png)

エイリアスの情報を入力します。
|入力/選択項目|内容|
|-- |-- |
|Alias name|任意のエイリアス名|
|Description|エイリアスの説明文|
|Create a new version and associate it to this alias. / Use an existing version to associate this alias.| エイリアスを新しいバージョンと既存バージョンのどちらに紐付けるか|

![エイリアスの情報](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/e13f986f-ec08-cf1e-7c59-29ad85145987.png)

エイリアスを作成すると､バージョンとともに以下のようにリストが表示されます｡APIからAgentsを呼び出す際に`Alias ID`を使用します｡ **Alias IDは後述のSecret Managerのシークレット登録に使用します。**

![エイリアス一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/8b8a6c3c-ffc7-c04d-8641-95d223982f70.png)

Agentsの設定変更はの`Working draft`の項目から行えます｡なかでもAdvanced promptsでは､言語モデルに対して前処理や後処理の詳細な指示テンプレートを上書き/拡張できます｡
設定を変更した際はplaygroundで動作確認が行ったあと､エイリアスを作成します｡

![Agentsのドラフト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/3f5584cc-b4eb-e3f4-ca2b-7d540f09fcf0.png)

Working draft内にあるAdvanced promptsの項目で､Editをクリック｡
![Advanced promptsg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/15009ec3-ae1b-3767-4901-32c04010788b.png)

プロンプトや､Temperature､出力の長さなどがカスタマイズできます｡
![![Advanced promptsの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/15009ec3-ae1b-3767-4901-32c04010788b.png)
g](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/cb97973d-c111-621c-7ce5-8250738b3457.png)

### Agentsのシークレット情報をSecret Managerに登録

AgentsのIDとAlias IDをSecret Managerに登録します。登録先のシークレットは、SlackのSlackSigningSecretやSlackBotTokenを登録したものです。
あわせて、BacklogのAPIキーと自身のBacklogのURLを登録します。BacklogのURLは、https://[スペースID].backlog.com/ もしくはhttps://[スペースID].backlog.jp/ です。

![Secret Manager](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61809/517d8f68-5256-9548-e10d-be55e90fe9a4.png)

## 動作確認

任意のチャンネンルに､`@aws-sam-bedrock-action-group` (Slack Appの作成時に設定した名前)を招待し､メンション形式で依頼をポストします｡動作しない場合のログやOpenAI APIが返すレスポンスは CloudWatch Logs に出力されているログが参考になります｡

## 作成したリソースの削除

最後に､作成したアプリケーションを削除する手順です｡リソースを削除するには sam delete コマンドを実行します｡

```console
sam delete
```

## まとめ

Agents for Amazon BedrockとAction groupsを使用することで､SlackアプリとBacklogのAPIを組み合わせて自然言語での問い合わせに対してBacklog課題やWikiを検索することができました｡Backlog公式のOpenAPIスキーマがないため自分で作成する必要がありましたが､その作成もGitHub Copilotの助けを借りてスムーズに進めることができました｡

このアプリケーションは､RAGと異なり検索の精度や結果はBacklog APIに異存するため､検索キーワードと類似性が高い課題やWikiを抽出するといったことができません｡Knowledge Bases for Amazon Bedrockで構築したRAGと組み合わせ､相互の結果をもとにAgentsに回答を求めることで､より高度な問い合わせに対応することができるかもしれません｡

前回の記事に引き続きAWS SAMを使用してアプリケーションを構築しましたが､今回はLambdaレイヤーやリソースベースポリシーを使用することで､Lambda関数の設定をより細かく行う設定を知ることができました｡