Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aws-step-functions/POWER.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Load the appropriate steering file based on what the user is working on:
- **Service integrations**, **Lambda invoke**, **DynamoDB**, **SNS**, **SQS**, **SDK integrations**, **Resource ARN**, **sync**, **async** → see `service-integrations.md`
- **Migrating from JSONPath to JSONata**, **migration**, **JSONPath to JSONata**, **InputPath**, **Parameters**, **ResultSelector**, **ResultPath**, **OutputPath**, **intrinsic functions**, **Iterator**, **payload template** → see `migrating-from-jsonpath-to-jsonata.md`
- **Validation**, **linting**, **testing**, **TestState**, **test state**, **mock**, **mocking**, **unit test**, **inspection level**, **DEBUG**, **TRACE**, **validate state**, **test in isolation** → see `validation-and-testing.md`
- **Architecture patterns**, **examples**, **polling**, **saga**, **compensation**, **scatter-gather**, **semaphore**, **lock**, **human-in-the-loop**, **escalation**, **Express to Standard** → see `architecture-patterns.md`
- **Architecture patterns**, **examples**, **polling**, **saga**, **compensation**, **scatter-gather**, **semaphore**, **lock**, **human-in-the-loop**, **escalation**, **Express to Standard**, **agent**, **harness** → see `architecture-patterns.md`
- **Data transformation**, **JSONata expressions**, **filtering**, **aggregation**, **string operations**, **$reduce**, **$lookup**, **$toMillis**, **$partition**, **$parse**, **$hash**, **$uuid** → see `transforming-data.md`
- **State input/output**, **$states**, **Assign**, **Output**, **Arguments**, **variable scope**, **variable limits**, **evaluation order**, **passing data between states** → see `processing-state-inputs-and-outputs.md`

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
{
"Comment": "Customer-support ticket triage using Bedrock AgentCore invokeHarness with role-specific system prompts and a DynamoDB record.",
"QueryLanguage": "JSONata",
"StartAt": "Analyze Ticket",
"States": {
"Analyze Ticket": {
"Type": "Task",
"Resource": "arn:aws:states:::bedrockagentcore:invokeHarness",
"Arguments": {
"HarnessArn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:harness/support-triage",
"RuntimeSessionId": "{% $states.context.Execution.Name & '-analyze' %}",
"Messages": [
{
"Role": "user",
"Content": [
{
"Text": "{% 'Customer tier: ' & $states.input.ticket.customer_tier & '\\nSubject: ' & $states.input.ticket.subject & '\\nBody: ' & $states.input.ticket.body %}"
}
]
}
],
"SystemPrompt": [
{
"Text": "You are a support-ticket analyst. Respond with EXACTLY one JSON object and nothing else. Do not include <thinking> tags. Do not include reasoning. Do not include prose. Do not include markdown. The JSON must have exactly three keys: category (one of: billing, technical, account, other), sentiment (one of: frustrated, neutral, satisfied), urgency (one of: low, medium, high). Account for customer_tier when assessing urgency. The first character of your response must be { and the last character must be }."
}
],
"Model": {
"BedrockModelConfig": {
"ModelId": "amazon.nova-lite-v1:0"
}
},
"MaxTokens": 256
},
"Assign": {
"ticket": "{% $states.input.ticket %}",
"analysis": "{% $parse('{' & $substringBefore($substringAfter($states.result.Output.Message.Content[0].Text, '{'), '}') & '}') %}"
},
"Retry": [
{
"ErrorEquals": [
"BedrockAgentCore.ThrottlingException",
"BedrockAgentCore.InternalServerException"
],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Assign": {
"failedStep": "Analyze Ticket",
"errorInfo": "{% $states.errorOutput %}"
},
"Next": "Triage Failed"
}
],
"Next": "Recommend Action"
},
"Recommend Action": {
"Type": "Task",
"Resource": "arn:aws:states:::bedrockagentcore:invokeHarness",
"Arguments": {
"HarnessArn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:harness/support-triage",
"RuntimeSessionId": "{% $states.context.Execution.Name & '-recommend' %}",
"Messages": [
{
"Role": "user",
"Content": [
{
"Text": "{% 'Ticket: ' & $string($ticket) & '\\nAnalysis: ' & $string($analysis) %}"
}
]
}
],
"SystemPrompt": [
{
"Text": "You are a triage director. Respond with EXACTLY one JSON object and nothing else. Do not include <thinking> tags. Do not include reasoning. Do not include prose. Do not include markdown. The JSON must have exactly two keys: recommended_action (one of: auto_resolve, route_to_billing, route_to_technical, route_to_account_management, escalate_to_specialist) and summary (one or two sentences a human agent can read in five seconds). The first character of your response must be { and the last character must be }."
}
],
"Model": {
"BedrockModelConfig": {
"ModelId": "amazon.nova-lite-v1:0"
}
},
"MaxTokens": 512
},
"Assign": {
"recommendation": "{% $parse('{' & $substringBefore($substringAfter($states.result.Output.Message.Content[0].Text, '{'), '}') & '}') %}"
},
"Retry": [
{
"ErrorEquals": [
"BedrockAgentCore.ThrottlingException",
"BedrockAgentCore.InternalServerException"
],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"Assign": {
"failedStep": "Recommend Action",
"errorInfo": "{% $states.errorOutput %}"
},
"Next": "Triage Failed"
}
],
"Next": "Record Triage"
},
"Record Triage": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:putItem",
"Arguments": {
"TableName": "TicketTriageTable",
"Item": {
"ticket_id": { "S": "{% $ticket.id %}" },
"category": { "S": "{% $analysis.category %}" },
"sentiment": { "S": "{% $analysis.sentiment %}" },
"urgency": { "S": "{% $analysis.urgency %}" },
"recommended_action": { "S": "{% $recommendation.recommended_action %}" },
"summary": { "S": "{% $recommendation.summary %}" },
"triaged_at": { "S": "{% $now() %}" }
}
},
"Output": {
"ticket_id": "{% $ticket.id %}",
"category": "{% $analysis.category %}",
"sentiment": "{% $analysis.sentiment %}",
"urgency": "{% $analysis.urgency %}",
"recommended_action": "{% $recommendation.recommended_action %}",
"summary": "{% $recommendation.summary %}"
},
"End": true
},
"Triage Failed": {
"Type": "Fail",
"Error": "TriageError",
"Cause": "{% 'Triage failed at ' & $failedStep & ': ' & ($exists($errorInfo.Cause) ? $errorInfo.Cause : 'Unknown error') %}"
}
}
}
17 changes: 17 additions & 0 deletions aws-step-functions/steering/architecture-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,23 @@ See `examples/human-in-the-loop-with-timeout-escalation.asl.json`

---

## Agent Orchestration with Bedrock AgentCore

Use the `bedrockagentcore:invokeHarness` optimized integration to chain multiple AI agent calls with role-specific system prompts. Each call gets a unique `RuntimeSessionId` (derived from the execution name) so sessions don't collide. Parse structured JSON from model output using the assistant-prefill technique and JSONata `$parse`.

See `examples/agent-orchestration-with-agentcore.asl.json`

Key elements:
- Resource: `arn:aws:states:::bedrockagentcore:invokeHarness` — Request/Response only (`.sync` and `.waitForTaskToken` not supported).
- `RuntimeSessionId` scoped per step (`$states.context.Execution.Name & '-analyze'`) to keep sessions independent.
- Assistant prefill (`"Role": "assistant", "Content": [{"Text": "{"}]`) forces JSON output from the model.
- `$parse('{' & $substringBefore($substringAfter(..., '{'), '}') & '}')` extracts structured data from the response.
- `Assign` stores parsed results as workflow variables (`$analysis`, `$recommendation`) for downstream states.
- Retry on `BedrockAgentCore.ThrottlingException` and `BedrockAgentCore.InternalServerException` with exponential backoff.
- IAM requires `bedrock-agentcore:InvokeHarness` and `bedrock-agentcore:InvokeAgentRuntime` on the harness ARN (note: hyphen in IAM service name, no hyphen in resource URI).

---

## Express → Standard Handoff

Express workflows are more cost-effective for high volume State Machine Invocations, but don't support callbacks or long waits. Standard workflows handle those but cost per state transition. Use Express for fast, high-volume ingest and kick off a Standard execution for the long-running tail.
Expand Down
32 changes: 32 additions & 0 deletions aws-step-functions/steering/service-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,38 @@ Note: The `.sync:2` suffix waits for completion. The child output is a JSON stri

---

### Bedrock AgentCore (Invoke Harness)

#### Optimized Integration (Request/Response Only)

```json
"InvokeAgent": {
"Type": "Task",
"Resource": "arn:aws:states:::bedrockagentcore:invokeHarness",
"Arguments": {
"HarnessArn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:harness/my-agent",
"RuntimeSessionId": "{% $states.context.Execution.Name & '-step1' %}",
"Messages": [
{
"Role": "user",
"Content": [{ "Text": "{% $states.input.userMessage %}" }]
}
],
"SystemPrompt": [{ "Text": "You are a helpful assistant." }],
"MaxIterations": 75,
"TimeoutSeconds": 600
},
"Output": "{% $states.result.Output.Message.Content[0].Text %}",
"Next": "NextState"
}
```

Note: Only Request/Response is supported — `.sync` and `.waitForTaskToken` are not available. The resource URI uses `bedrockagentcore` (no hyphen), but IAM ARNs use `bedrock-agentcore` (with hyphen). Maximum `TimeoutSeconds` is 900. IAM role needs both `bedrock-agentcore:InvokeHarness` and `bedrock-agentcore:InvokeAgentRuntime` permissions on the harness ARN.

Response shape: `$states.result` contains `Output.Message` (Converse-shaped), `StopReason`, `Usage` (InputTokens, OutputTokens, TotalTokens), and `Metrics` (LatencyMs).

---

### Cross-Account Access

Use the `Credentials` field to assume a role in another account:
Expand Down
Loading