Skip to content

Commit c9097b1

Browse files
committed
chore(doc): add examples of outputs
1 parent 96c6cdc commit c9097b1

11 files changed

Lines changed: 281 additions & 87 deletions

File tree

.projenrc.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ project.postCompileTask.exec('cd cli && npx projen build');
333333
// ---------------------------------------------------------------------------
334334
// Docs site subproject (Astro + Starlight)
335335
// ---------------------------------------------------------------------------
336+
/** GitHub Pages project segment; must match Astro `base` and public asset URLs in mirrored markdown. */
337+
const DOCS_ASTRO_BASE = '/sample-autonomous-cloud-coding-agents';
338+
336339
const docsSite = new javascript.NodeProject({
337340
parent: project,
338341
outdir: 'docs',
@@ -375,7 +378,7 @@ new TextFile(docsSite, 'astro.config.mjs', {
375378
'',
376379
'export default defineConfig({',
377380
" site: 'https://aws-samples.github.io',",
378-
" base: '/sample-autonomous-cloud-coding-agents',",
381+
` base: '${DOCS_ASTRO_BASE}',`,
379382
' integrations: [',
380383
' starlight({',
381384
" title: 'ABCA Docs',",
@@ -513,8 +516,8 @@ new TextFile(docsSite, 'src/content/docs/index.md', {
513516
*/
514517
function ensureFrontmatter(content: string, title: string): string {
515518
const normalizedContent = content
516-
.replaceAll('../imgs/', '/imgs/')
517-
.replaceAll('../diagrams/', '/diagrams/')
519+
.replaceAll('../imgs/', `${DOCS_ASTRO_BASE}/imgs/`)
520+
.replaceAll('../diagrams/', `${DOCS_ASTRO_BASE}/diagrams/`)
518521
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match: string, label: string, target: string) => {
519522
const rewritten = rewriteDocsLinkTarget(target);
520523
return rewritten ? `[${label}](${rewritten})` : match;

agent/README.md

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ No other permissions are needed.
3232

3333
The agent uses Amazon Bedrock for Claude inference. You need credentials with `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` permissions.
3434

35-
Two options for passing credentials to the container:
35+
Common ways to pass credentials into the container (when using `run.sh`):
3636

3737
**Option A** — Environment variables:
3838
```bash
@@ -42,7 +42,9 @@ export AWS_SESSION_TOKEN="..." # if using temporary credentials
4242
export AWS_REGION="us-east-1"
4343
```
4444

45-
**Option B** — AWS profile (mounts `~/.aws` read-only):
45+
**Option B** — AWS CLI resolution (recommended for SSO): `run.sh` runs `aws configure export-credentials` when the AWS CLI is installed, so you can use `aws sso login` and optionally `AWS_PROFILE` without mounting `~/.aws`.
46+
47+
**Option C** — Mount `~/.aws` read-only (static access keys in files; SSO often does not work inside the container):
4648
```bash
4749
export AWS_PROFILE="my-profile"
4850
export AWS_REGION="us-east-1"
@@ -53,6 +55,7 @@ export AWS_REGION="us-east-1"
5355
```bash
5456
export GITHUB_TOKEN="ghp_..."
5557
export AWS_REGION="us-east-1"
58+
# Either export keys, or run `aws sso login` (and optionally AWS_PROFILE) and let run.sh resolve credentials
5659
export AWS_ACCESS_KEY_ID="..."
5760
export AWS_SECRET_ACCESS_KEY="..."
5861

@@ -86,19 +89,19 @@ The `run.sh` script overrides the container's default CMD to run `python /app/en
8689
|----------|----------|---------|-------------|
8790
| `GITHUB_TOKEN` | Yes | | Fine-grained PAT (see permissions above) |
8891
| `AWS_REGION` | Yes | | AWS region for Bedrock (e.g., `us-east-1`) |
89-
| `AWS_ACCESS_KEY_ID` | Yes* | | AWS credentials |
90-
| `AWS_SECRET_ACCESS_KEY` | Yes* | | AWS credentials |
92+
| `AWS_ACCESS_KEY_ID` | Conditional† | | Explicit keys, if you are not using CLI-based resolution |
93+
| `AWS_SECRET_ACCESS_KEY` | Conditional† | | Explicit keys, if you are not using CLI-based resolution |
9194
| `AWS_SESSION_TOKEN` | No | | For temporary credentials |
92-
| `AWS_PROFILE` | Yes* | | Alternative to explicit keys (mounts `~/.aws`) |
95+
| `AWS_PROFILE` | No | | Profile for `aws configure export-credentials` in `run.sh`, or default profile when using the `~/.aws` mount fallback |
9396
| `ANTHROPIC_MODEL` | No | `us.anthropic.claude-sonnet-4-6` | Bedrock model ID |
9497
| `MAX_TURNS` | No | `100` | Max agent turns before stopping |
95-
| `MAX_BUDGET_USD` | No | | Max cost budget in USD (0.01–100). Agent stops when budget is reached. |
98+
| `MAX_BUDGET_USD` | No | | **Local batch only** (shell env when running `entrypoint.py` directly). Range 0.01–100; agent stops when the budget is reached. For deployed AgentCore **server** mode and production tasks, set **`max_budget_usd`** on task creation (REST API, CLI `--max-budget`, or Blueprint default); the orchestrator sends it in the `/invocations` JSON body — server mode does not read `MAX_BUDGET_USD` from the environment. |
9699
| `DRY_RUN` | No | | Set to `1` to validate config and print the prompt without running the agent |
97100
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | No | `anthropic.claude-haiku-4-5-20251001-v1:0` | Bedrock model ID for the pre-flight safety check (see below) |
98101

99102
**Pre-flight check model**: Claude Code runs a quick safety verification using a small Haiku model before executing each tool command. On Bedrock, the default Haiku model ID may not be enabled in your account, causing the check to time out with *"Pre-flight check is taking longer than expected"* warnings. The agent sets `ANTHROPIC_DEFAULT_HAIKU_MODEL` to a known-available Bedrock Haiku model ID to avoid this. If you see pre-flight timeout warnings, verify that this model is enabled in your Bedrock model access settings.
100103

101-
\* Provide either `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` or `AWS_PROFILE`.
104+
† You need valid Bedrock credentials in the container: export keys (Option A), let `run.sh` inject keys from the AWS CLI after `aws sso login` or similar (Option B), or mount `~/.aws` (Option C). `run.sh` also sets `CLAUDE_CODE_USE_BEDROCK=1` so Claude Code uses Bedrock.
102105

103106
### Examples
104107

@@ -111,6 +114,9 @@ ANTHROPIC_MODEL="us.anthropic.claude-sonnet-4-6" ./agent/run.sh "owner/repo" 42
111114

112115
# Limit agent to 50 turns
113116
MAX_TURNS=50 ./agent/run.sh "owner/repo" "Add unit tests for the auth module"
117+
118+
# Local batch only — cap cost (production tasks use API max_budget_usd instead)
119+
MAX_BUDGET_USD=5 ./agent/run.sh "owner/repo" "Small refactor"
114120
```
115121

116122
## AgentCore Runtime Mode
@@ -131,47 +137,51 @@ To be safe, the agent isolates each task into its own workspace directory:
131137

132138
**`GET /ping`** — Health check. Returns `{"status": "healthy"}`. Stays responsive while the agent runs.
133139

134-
**`POST /invocations`** — Run the agent. Blocks until complete.
140+
**`POST /invocations`** — Accept a task and start the agent in a **background thread**. The handler returns **immediately** with an acceptance payload; it does not wait for the agent to finish. While the task runs, progress and the final outcome are written to **DynamoDB** when `TASK_TABLE_NAME` is set (see `task_state.py`); the deployed platform polls that table via the orchestrator. For ad-hoc local testing without DynamoDB, follow **`docker logs -f bgagent-run`** (or your container name).
141+
142+
Request payload (representative fields — the API orchestrator sends a fuller object including hydrated GitHub/issue context):
135143

136-
Request payload:
137144
```json
138145
{
139146
"input": {
140-
"prompt": "update the rfc issue template to add a codeowners field",
147+
"task_id": "9e285dba622d",
141148
"repo_url": "owner/repo",
149+
"prompt": "update the rfc issue template to add a codeowners field",
142150
"issue_number": "",
143151
"max_turns": 100,
144152
"max_budget_usd": 5.0,
145-
"anthropic_model": "us.anthropic.claude-sonnet-4-6",
153+
"model_id": "us.anthropic.claude-sonnet-4-6",
146154
"aws_region": "us-east-1"
147155
}
148156
}
149157
```
150158

151-
All fields in `input` fall back to container environment variables if omitted. Secrets like `GITHUB_TOKEN` should be set as runtime environment variables via the CDK stack — not sent in the payload, since AgentCore logs the full request payload in plain text.
159+
- `task_id` — Correlates with DynamoDB and logs; if omitted for local experiments, the agent generates a short id.
160+
- `model_id` — Preferred key from the orchestrator; `anthropic_model` is also accepted.
161+
- Optional platform fields (when using the full stack) include `hydrated_context`, `system_prompt_overrides`, `prompt_version`, and `memory_id`.
162+
163+
All fields in `input` fall back to container environment variables when omitted. Secrets like `GITHUB_TOKEN` should be set as runtime environment variables via the CDK stack — not sent in the payload, since AgentCore logs the full request payload in plain text.
164+
165+
Immediate response (acceptance):
152166

153-
Response:
154167
```json
155168
{
156169
"output": {
157170
"message": {
158171
"role": "assistant",
159-
"content": [{"text": "PR created: https://github.com/owner/repo/pull/3"}]
172+
"content": [{"text": "Task accepted: 9e285dba622d"}]
160173
},
161174
"result": {
162-
"status": "success",
163-
"pr_url": "https://github.com/owner/repo/pull/3",
164-
"build_passed": true,
165-
"cost_usd": 0.3598,
166-
"turns": 18,
167-
"duration_s": 126.3,
175+
"status": "accepted",
168176
"task_id": "9e285dba622d"
169177
},
170178
"timestamp": "2026-02-20T01:00:00.000000+00:00"
171179
}
172180
}
173181
```
174182

183+
Final metrics (PR URL, cost, turns, build status, etc.) appear in **container logs**, in **DynamoDB** when configured, and in the **REST API** for deployed tasks (`GET /v1/tasks/{task_id}` via the `bgagent` CLI or HTTP client).
184+
175185
### Testing Server Mode Locally
176186

177187
Use `run.sh --server` to build and start the server locally. It handles credentials, port mapping, and resource constraints automatically:
@@ -218,7 +228,7 @@ bgagent submit --repo owner/repo --issue 42
218228
bgagent submit --repo owner/repo --issue 42 --wait
219229
```
220230

221-
For the full CLI reference, see the [User guide](docs/guides/USER_GUIDE.md).
231+
For the full CLI reference, see the [User guide](../docs/guides/USER_GUIDE.md).
222232

223233
## Monitoring a Running Agent
224234

@@ -247,13 +257,13 @@ The agent pipeline (shared by both modes):
247257
1. **Config validation** — checks required parameters
248258
2. **Context hydration** — fetches the GitHub issue (title, body, comments) if an issue number is provided
249259
3. **Prompt assembly** — combines the system prompt (behavioral contract) with the issue context and task description
250-
4. **Deterministic pre-hooks** — clones repo, creates branch, configures git auth, runs `mise trust`, `mise install`, and `mise run build`
260+
4. **Deterministic pre-hooks** — clones repo, creates branch, configures git auth, runs `mise trust`, `mise install`, `mise run build`, and `mise run lint`
251261
5. **Agent execution** — invokes the Claude Agent SDK via the `ClaudeSDKClient` class (connect/query/receive_response pattern) in unattended mode. The agent:
252262
- Understands the codebase
253263
- Makes changes, runs tests and linters
254264
- Commits and pushes after each unit of work
255265
- Creates a pull request with summary, testing notes, and decisions
256-
6. **Deterministic post-hooks** — verifies build (`mise run build`), ensures PR exists (creates one if the agent didn't)
266+
6. **Deterministic post-hooks** — verifies `mise run build` and `mise run lint`, ensures a PR exists (creates one if the agent did not)
257267
7. **Metrics** — returns duration, disk usage, turn count, cost, and PR URL
258268

259269
## Metrics
@@ -302,13 +312,21 @@ docker images bgagent-local --format "{{.Size}}"
302312

303313
```
304314
agent/
305-
├── Dockerfile Python 3.12 + Node.js 20 + Claude Code CLI + git + gh + mise (ARM64)
315+
├── Dockerfile Python 3.13 + Node.js 20 + Claude Code CLI + git + gh + mise (default platform linux/arm64)
306316
├── .dockerignore
307-
├── pyproject.toml Dependencies: claude-agent-sdk, requests, fastapi, uvicorn (no uvloop)
308-
├── entrypoint.py Config, context hydration, agent invocation via ClaudeSDKClient, metrics, run_task() entry point
309-
├── server.py FastAPI app — /invocations and /ping for AgentCore Runtime
310-
├── system_prompt.py Behavioral contract (PRD Section 11)
311-
├── run.sh Build + run helper for local/server mode with AgentCore constraints
312-
├── test_sdk_smoke.py Diagnostic: minimal SDK smoke test (ClaudeSDKClient → CLI → Bedrock)
317+
├── pyproject.toml App dependencies (claude-agent-sdk, FastAPI, boto3, OpenTelemetry distro, MCP, …)
318+
├── uv.lock Locked deps for reproducible `uv sync` in the image
319+
├── mise.toml Tool versions / tasks used when the target repo relies on mise
320+
├── entrypoint.py Config, context hydration, ClaudeSDKClient pipeline, metrics, run_task()
321+
├── server.py FastAPI — async /invocations (background thread) and /ping; OTEL session correlation
322+
├── task_state.py Best-effort DynamoDB task status (no-op if TASK_TABLE_NAME unset)
323+
├── observability.py OpenTelemetry helpers (e.g. AgentCore session id)
324+
├── memory.py Optional memory / episode integration for the agent
325+
├── system_prompt.py Behavioral contract (PRD Section 11)
326+
├── prepare-commit-msg.sh Git hook (Task-Id / Prompt-Version trailers on commits)
327+
├── run.sh Build + run helper for local/server mode with AgentCore constraints
328+
├── test_sdk_smoke.py Diagnostic: minimal SDK smoke test (ClaudeSDKClient → CLI → Bedrock)
313329
└── test_subprocess_threading.py Diagnostic: subprocess-in-background-thread verification
314330
```
331+
332+
The container **CMD** runs the app under `opentelemetry-instrument` with **uvicorn** using the **asyncio** event loop (not uvloop), avoiding known subprocess issues with uvloop.

agent/run.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Environment variables (required):
2828
Environment variables (optional):
2929
ANTHROPIC_MODEL Model to use (default: us.anthropic.claude-sonnet-4-6)
3030
DRY_RUN Set to 1 to validate config and print prompt without running the agent
31-
MAX_TURNS Max agent turns (default: 200)
31+
MAX_TURNS Max agent turns (default: 100)
3232
3333
AWS credentials — pick one method:
3434
Option A: Export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
@@ -154,6 +154,7 @@ DOCKER_ARGS=(
154154
[[ -n "${TASK_DESCRIPTION}" ]] && DOCKER_ARGS+=(-e "TASK_DESCRIPTION=${TASK_DESCRIPTION}")
155155
[[ -n "${DRY_RUN:-}" ]] && DOCKER_ARGS+=(-e "DRY_RUN=${DRY_RUN}")
156156
[[ -n "${MAX_TURNS:-}" ]] && DOCKER_ARGS+=(-e "MAX_TURNS=${MAX_TURNS}")
157+
[[ -n "${MAX_BUDGET_USD:-}" ]] && DOCKER_ARGS+=(-e "MAX_BUDGET_USD=${MAX_BUDGET_USD}")
157158

158159
# Server mode: expose port 8080
159160
if [[ "$MODE" == "server" ]]; then

docs/guides/DEVELOPER_GUIDE.md

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Clone the repository and open the project root (commands below assume your shell
5353

5454
```bash
5555
git clone https://github.com/aws-samples/sample-autonomous-cloud-coding-agents.git
56-
cd bgagent
56+
cd sample-autonomous-cloud-coding-agents
5757
```
5858

5959
### Pre-requisites
@@ -74,7 +74,7 @@ Default output format [None]: json
7474
- [Python](https://www.python.org/downloads/) >=3.9
7575
- [Projen](https://github.com/projen/projen/releases/tag/v0.98.26) >= 0.98.26
7676
- [Yarn](https://classic.yarnpkg.com/lang/en/docs/cli/install/) >= 1.22.19
77-
- [mise](https://mise.jdx.dev/) (required for local agent Python tasks and checks)
77+
- [mise](https://mise.jdx.dev/getting-started.html) (required for local agent Python tasks and checks)
7878
- [Docker](https://docs.docker.com/engine/install/)
7979
- A **GitHub personal access token** (PAT) with permission to access every repository you onboard (clone, push to branches, create and update pull requests). After deployment, store it in the Secrets Manager secret the stack creates ([Post-deployment setup](#post-deployment-setup)); for local agent runs, export `GITHUB_TOKEN` (see **Local testing** below). Required scopes are documented in `agent/README.md`.
8080

@@ -88,8 +88,9 @@ aws xray update-trace-segment-destination --destination CloudWatchLogs
8888

8989
Without this, `cdk deploy` will fail with: *"X-Ray Delivery Destination is supported with CloudWatch Logs as a Trace Segment Destination."*
9090

91-
You can use the command below to install the dependencies listed above
92-
```
91+
Install [mise](https://mise.jdx.dev/getting-started.html) using the official guide; it is not installed via npm. For the Node-based CLIs, run:
92+
93+
```bash
9394
npm install -g npm aws-cdk yarn projen
9495
```
9596

@@ -188,11 +189,13 @@ docker exec -it bgagent-run bash # shell into the container
188189
| `MAX_TURNS` | `100` | Max agent turns before stopping |
189190
| `DRY_RUN` | | Set to `1` to validate config and print prompt without running the agent |
190191

192+
**Cost budget** is not configured here for production tasks: set **`max_budget_usd`** when creating a task (REST API, CLI `--max-budget`, or per-repo Blueprint). The orchestrator passes it in the runtime invocation payload. The optional env var `MAX_BUDGET_USD` applies only to **local batch** runs; see `agent/README.md`.
193+
191194
For the full list of environment variables and GitHub PAT permissions, see `agent/README.md`.
192195

193196
### Deployment
194197

195-
Once your agent works locally, you can deploy it on AWS.
198+
Once your agent works locally, you can deploy it on AWS. A **full** `npx projen deploy` of this stack has been observed at **~572 seconds (~9.5 minutes)** total (CDK-reported *Total time*); expect variation by Region, account state, and whether container layers are already cached.
196199

197200
1. Generate project files (dependencies, etc.) from the configuration file and install them.
198201

@@ -242,19 +245,33 @@ aws cloudformation describe-stacks --stack-name backgroundagent-dev \
242245
--query 'Stacks[0].Outputs' --output table
243246
```
244247

248+
Use the **same AWS Region** (and profile) as `npx projen deploy`. If you omit `--region`, the CLI uses your default from `aws configure`; when the stack lives in another Region, `describe-stacks` fails, **stderr** shows the error, and capturing stdout into a shell variable (for example `SECRET_ARN=$(...)`) yields **empty** with no obvious hint—run the `aws` command without `$(...)` to see the message. Add `--region your-region` to every command below if needed.
249+
250+
If `put-secret-value` returns **`Invalid endpoint: https://secretsmanager..amazonaws.com`** (note the **double dot**), the effective Region string is **empty**—for example `REGION=` was never set, `export REGION` is blank, or `--region "$REGION"` expands to nothing. Set `REGION` to a real value (e.g. `us-east-1`) or run `aws configure set region your-region` so the default is non-empty.
251+
245252
#### Set the GitHub token
246253

247254
The agent reads the GitHub personal access token from Secrets Manager at startup. After deploying, store your PAT in the secret:
248255

249256
```bash
250-
SECRET_ARN=$(aws cloudformation describe-stacks --stack-name backgroundagent-dev \
251-
--query 'Stacks[0].Outputs[?OutputKey==`GitHubTokenSecretArn`].OutputValue' --output text)
257+
# Same Region you deployed to (example: us-east-1). Must be non-empty—see note above
258+
# about "Invalid endpoint: ...secretsmanager..amazonaws.com".
259+
REGION=us-east-1
260+
261+
SECRET_ARN=$(aws cloudformation describe-stacks \
262+
--stack-name backgroundagent-dev \
263+
--region "$REGION" \
264+
--query 'Stacks[0].Outputs[?OutputKey==`GitHubTokenSecretArn`].OutputValue | [0]' \
265+
--output text)
252266

253267
aws secretsmanager put-secret-value \
254-
--secret-id $SECRET_ARN \
268+
--region "$REGION" \
269+
--secret-id "$SECRET_ARN" \
255270
--secret-string "ghp_your_fine_grained_pat_here"
256271
```
257272

273+
If `SECRET_ARN` is still empty after setting `REGION`, list outputs in that Region (`describe-stacks``--query 'Stacks[0].Outputs' --output table`) and confirm the row `GitHubTokenSecretArn` exists—wrong stack name or an incomplete deployment are the other common causes.
274+
258275
See `agent/README.md` for the required PAT permissions.
259276

260277
#### Onboard repositories

0 commit comments

Comments
 (0)