A deliberately small AI agent implementation that demonstrates how tool calling works without hiding the control flow behind an agent framework. The agent uses the Anthropic SDK to reason about a request, invokes a read-only AWS STS tool through boto3, returns the tool result to the model, and continues until the model produces a final answer.
Frameworks make agents quick to assemble, but they can hide the mechanics that matter when debugging or securing them. This project keeps the complete loop in one Python file so the following behavior is easy to inspect:
- Define a tool and its JSON input schema.
- Send the user message and tool definition to Claude.
- Detect a
tool_useresponse. - Execute the requested local function.
- Correlate the result with Claude's
tool_use_id. - Append the assistant tool request and user tool result to the conversation.
- Repeat until Claude returns
end_turn.
User request
│
▼
Anthropic Messages API
│
├── end_turn ───────────────► final text response
│
└── tool_use: aws_whoami
│
▼
boto3 STS client
│
▼
GetCallerIdentity result
│
└─────────────► tool_result sent back to Claude
| Tool | AWS API | Input | Output |
|---|---|---|---|
aws_whoami |
STS GetCallerIdentity |
No arguments | AWS account ID, principal ARN, and user ID |
GetCallerIdentity is read-only. The agent does not modify AWS resources.
aws-agent-loop/
├── agent.py # Tool definition, executor, and multi-turn agent loop
├── README.md
├── LICENSE
└── .gitignore
- Python 3.10+
- AWS credentials available to boto3
- Anthropic API key
Install the dependencies in a virtual environment:
git clone https://github.com/jmac052002/aws-agent-loop.git
cd aws-agent-loop
python3 -m venv .venv
source .venv/bin/activate
pip install anthropic boto3 python-dotenvCreate a local .env file:
ANTHROPIC_API_KEY=your_anthropic_api_key
AWS_PROFILE=your_read_only_profile
AWS_DEFAULT_REGION=us-east-1The repository's .gitignore excludes .env. Do not commit API keys or AWS credentials.
Before running the agent, verify the active AWS identity directly:
aws sts get-caller-identity --profile "$AWS_PROFILE"python agent.pyThe current entry point asks:
What AWS account am I currently running in?
A successful run produces a natural-language response grounded in the STS identity returned by the tool. Account-specific values are intentionally not included in this README.
The essential implementation is intentionally direct:
while True:
response = client.messages.create(
model=MODEL,
max_tokens=1024,
tools=tools,
messages=messages,
)
if response.stop_reason == "end_turn":
return final_text(response)
if response.stop_reason == "tool_use":
tool_results = execute_requested_tools(response.content)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})The production code in agent.py contains the concrete response parsing and tool-result correlation.
- No agent framework: keeps the Anthropic message protocol and state transitions visible.
- Explicit tool allowlist: only names present in
run_toolcan execute. - Schema-defined inputs: Claude receives a machine-readable contract for every tool.
- Read-only first tool: STS identity inspection is useful for validating the pattern without introducing mutation risk.
- Normalized AWS failures: boto3 and botocore errors are returned to the model instead of terminating the process without context.
- Conversation preservation: the assistant's tool request and corresponding result remain in message history for the next model turn.
This is a focused learning reference, not a production autonomous-remediation service.
- It currently exposes one read-only AWS tool.
- The demonstration prompt is defined in
agent.pyrather than accepted through a CLI. - There is no retry policy, tool timeout, cost limit, or maximum loop-iteration guard yet.
- There is no automated test suite yet.
- The model identifier is configured as a constant in the source.
Those limitations are intentional and documented so the repository represents what the code does today.
- Use a dedicated least-privilege AWS profile.
- Keep Anthropic and AWS credentials outside source control.
- Treat future state-changing tools as privileged operations requiring validation, bounded inputs, audit logging, and human approval.
- Add a maximum iteration count before extending the loop with a larger toolset.