Task 0 · 8 tasks
Setup check
Clone the repo, connect to AWS, and confirm your database copy and model access before Alice's first request lands.
The “Getting Started” challenge
Welcome to DataStream Corp, a 1,200-person tech company whose CEO, Alice Chen, wants an AI assistant that actually knows the business. You are the developer she hired to build it.
Before you write a line of agent code, make sure the plumbing works: the code, your AWS identity, the company database and a route to a model.
Build it
Clone the repository
terminal · macOS / Linux / Windowsgit clone https://github.com/Opsfleet/agentic-workshop-aws.git cd agentic-workshop-aws git checkout genai-bootcamp cd bootcampInstall the tools
You need uv, Terraform (Phase 2 drives it for you; you never edit it) and the AWS CLI v2.
terminal · macOS / Linuxcurl -LsSf https://astral.sh/uv/install.sh | sh brew tap hashicorp/tap brew install hashicorp/tap/terraform awscli # Terraform >= 1.9 uv --version && terraform -version && aws --versionterminal · Windows PowerShellpowershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" winget install Hashicorp.Terraform Amazon.AWSCLI uv --version; terraform -version; aws --versionConnect to AWS with SSO
Your instructor gives you an SSO start URL and a region. Create a named profile, log in and check who you are:
terminal · macOS / Linux / Windowsaws configure sso # paste the start URL and region; name the profile, e.g. bootcamp aws sso login --profile bootcamp aws sts get-caller-identity --profile bootcampThe last command prints your SSO identity. SSO sessions expire after some hours; just run
aws sso login --profile bootcampagain.Sync the project and create your .env
terminal · macOS / Linuxuv sync cp .env.example .envterminal · Windows PowerShelluv sync Copy-Item .env.example .envFill in your name (from the instructor) and the profile you just created.
AWS_PROFILEis required when you use SSO; leave it blank only if your credentials come from environment variables..envPARTICIPANT=alice # your name, lowercase letters/digits AWS_PROFILE=bootcamp # required with SSO: the profile from the previous step BOOTCAMP_REGION=us-east-1 # from your instructor (falls back to AWS_REGION) MODEL_ID=gpt-6-luna # or claude-sonnet-5-5 for harder tasks BOOTCAMP_ROLE_ARN= # optional override; leave empty ENABLE_CODE_INTERPRETER=false # optional Phase 2 add-on ENABLE_BROWSER=false # optional Phase 2 add-onFrom here on, every
bootcamp.pycommand starts from your SSO profile and automatically assumes the rolebootcamp-participant-<name>. That role is what the platform recognises you by. Credentials refresh automatically, so long chats don't hit a one-hour limit, andaws loginprofiles work too. If something is wrong, the CLI prints a one-line fix, for exampleaws sso login --profile bootcampwhen your SSO session has expired.Meet your model gateway
Every model call in this bootcamp goes through the Opsfleet LiteLLM gateway. You never call Bedrock directly: your role can't. And there is no API key: each request carries a presigned AWS identity, and the gateway maps your role to your personal budget (default $1), which is plenty for the cheap default model.
terminaluv run bootcamp.py llmIf this prints
LITELLM_BASE_URL,MODELS, yourMODEL_IDand yourBUDGET(spent of max), the role assumption and keyless identity both work. If your budget runs out, model calls fail with HTTP 429budget_exceeded; ask your instructor for a top-up.Model When to use it gpt-6-lunaDefault. OpenAI GPT-6 Luna on Bedrock: small, fast, cheap. claude-sonnet-5-5Set MODEL_IDin.envwhen routing or reasoning gets hard. Costs more of your budget.Run the setup check
terminaluv run bootcamp.py phase1 t0It downloads your own copy of the DataStream SQLite database into
phase1/, counts employees, checks your AWS identity, builds a test agent and makes a real model call through the gateway.
Check your work
Phase 1 has no automated test: you check it by running the task and looking for the result below.
Every line starts with PASS, including LiteLLM gateway, ending with Setup complete, ready for Task 1. You should see roughly 1,200 employees and departments such as Engineering, Sales, Marketing, HR, Finance and Operations.
uv run bootcamp.py phase1 t0Under the hood
bootcamp.py phase1 t0 runs phase1/t0_setup.py with your .env loaded and your participant role assumed. The shared helpers live in phase1/common.py; the one that matters most is the model factory:
import litellm_gateway
MODEL_ID = os.getenv("MODEL_ID", "gpt-6-luna")
def make_model() -> OpenAIModel:
"""Every task talks to the model through the Opsfleet LiteLLM gateway (keyless, budgeted per participant)."""
return litellm_gateway.make_model(MODEL_ID)The heavy lifting is in shared/litellm_gateway.py, which Phase 2 reuses unchanged:
class StsIdentityAuth(httpx.Auth):
"""Adds a fresh presigned STS identity URL to each request (cached until shortly before it expires)."""
def auth_flow(self, request: httpx.Request):
request.headers[IDENTITY_HEADER] = self.identity_url() # X-Amz-Sts-Identity-Url
yield request
class GatewayModel(OpenAIModel):
"""Strands OpenAIModel bound to the gateway."""
def __init__(self, base_url: str, api_key: str | None = None, session: boto3.Session | None = None, **config):
super().__init__(
client_args={"base_url": f"{base_url.rstrip('/')}/v1", "api_key": api_key or KEYLESS_PLACEHOLDER}, **config
)
self._auth = None if api_key else StsIdentityAuth(session)
def make_model(model_id: str | None = None, base_url: str | None = None, **params) -> OpenAIModel:
"""Strands model routed through the gateway; reads MODEL_ID / LITELLM_BASE_URL / LITELLM_API_KEY from env."""
return GatewayModel(
base_url or os.environ["LITELLM_BASE_URL"],
os.getenv("LITELLM_API_KEY"),
model_id=model_id or os.getenv("MODEL_ID", "gpt-6-luna"),
params=params or None,
)Strands' OpenAIModel speaks the OpenAI chat-completions API, which LiteLLM exposes and translates to Bedrock. GatewayModel is a thin subclass: instead of a key, its StsIdentityAuth hook adds the X-Amz-Sts-Identity-Url header, a presigned STS GetCallerIdentity URL signed with your own credentials. The gateway replays it, learns you are bootcamp-participant-alice, and bills alice's budget. LITELLM_BASE_URL is filled in by the CLI; LITELLM_API_KEY is optional, only for tools that can't do keyless auth.