Sophia Ponte
02/19/2026, 6:19 PMMarvin
02/19/2026, 6:19 PMNate
02/19/2026, 6:20 PMenv on the job_variables if you don't already have the secret injected in the podNate
02/19/2026, 6:20 PMNate
02/19/2026, 6:23 PMMarvin
02/19/2026, 6:24 PMANTHROPIC_API_KEY in a Kubernetes Secret synced by ESO and inject it as an env var into your worker pod.
from prefect import flow, task
import os
import anthropic
import backoff
@task(
name="claude_message",
retries=3,
retry_delay_seconds=[5, 10, 30],
timeout_seconds=120,
tags=["anthropic"] # optional: tie to a concurrency limit
)
def claude_message(user_prompt: str) -> str:
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
@backoff.on_exception(backoff.expo, (anthropic.RateLimitError, anthropic.APIStatusError), max_time=60)
def _call():
resp = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=800,
temperature=0,
messages=[{"role": "user", "content": user_prompt}],
)
# Messages API returns content as a list of blocks
parts = []
for block in resp.content:
if block.type == "text":
parts.append(block.text)
return "\n".join(parts)
return _call()
@flow(name="llm-flow")
def llm_flow(prompt: str = "Summarize Prefect in 3 bullet points"):
result = claude_message(prompt)
return result
if __name__ == "__main__":
llm_flow()
Option B — Amazon Bedrock (Claude) via IRSA
- Best if you prefer IAM over API keys and want zero secret rotation.
- Attach an IAM role (via IRSA) to your Kubernetes worker service account with bedrock:InvokeModel permissions for your chosen model.
from prefect import flow, task
import json
import boto3
import backoff
import os
# Optionally set region via env var on the worker pod: AWS_REGION
BEDROCK_REGION = os.getenv("AWS_REGION", "us-east-1")
MODEL_ID = "anthropic.claude-3-5-sonnet-20241022-v1:0"
@task(
name="claude_message_bedrock",
retries=3,
retry_delay_seconds=[5, 10, 30],
timeout_seconds=120,
tags=["anthropic"] # optional: tie to a concurrency limit
)
def claude_message_bedrock(user_prompt: str) -> str:
client = boto3.client("bedrock-runtime", region_name=BEDROCK_REGION)
body = {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 800,
"temperature": 0,
"messages": [{"role": "user", "content": [{"type": "text", "text": user_prompt}]}],
}
@backoff.on_exception(backoff.expo, Exception, max_time=60)
def _call():
resp = client.invoke_model(
modelId=MODEL_ID,
body=json.dumps(body),
contentType="application/json",
accept="application/json",
)
payload = json.loads(resp["body"].read().decode("utf-8"))
parts = []
for block in payload.get("output", {}).get("content", []):
if block.get("type") == "text":
parts.append(block.get("text", ""))
return "\n".join(parts)
return _call()
@flow(name="llm-flow-bedrock")
def llm_flow_bedrock(prompt: str = "Summarize Prefect in 3 bullet points"):
result = claude_message_bedrock(prompt)
return result
if __name__ == "__main__":
llm_flow_bedrock()
Kubernetes worker + deployment pointers
- Create a Kubernetes work pool:
prefect work-pool create "eks-pool" --type kubernetesMarvin
02/19/2026, 6:24 PMprefect worker start -p "eks-pool"
- Deploy your flow from source (recommended in 3.x):
prefect deploy ./flows/llm_flow.py:llm_flow -n llm-deploy -p eks-pool
Secrets on EKS
- Direct Anthropic API:
- Use External Secrets Operator to sync ANTHROPIC_API_KEY from AWS Secrets Manager into a Kubernetes Secret.
- Add that Secret as env to your Kubernetes work pool’s base job template (or annotate your worker Deployment) so the task sees ANTHROPIC_API_KEY.
- Bedrock:
- Use IRSA to attach an IAM role that allows bedrock:InvokeModel. No API key needed.
Concurrency and cost controls (optional but recommended)
- Tag the task as shown (tags=["anthropic"]) and create a limit:
prefect concurrency-limit create anthropic --limit 2
- This caps simultaneous model calls across your org for that tag.
Operational tips
- Avoid logging prompts/responses unless necessary; if you do, redact sensitive data.
- For very large responses, consider persist_result=False on the task or configure S3/MinIO result storage.
- If you need streaming or tool use/function calling, we can adapt the task to Anthropic’s streaming or tools params. Just let me know your needs.
A couple of quick questions to tailor this:
- Do you prefer direct Anthropic API or Amazon Bedrock?
- Which Claude model do you want to standardize on?
- Do you need streaming responses or tool use/function calling?
- Any target throughput so we can size concurrency limits appropriately?
Docs
- Prefect Deploy: https://docs.prefect.io/latest/deploy/
- Workers and Work Pools (Kubernetes): https://docs.prefect.io/latest/
- Anthropic Python SDK: https://docs.anthropic.com/en/api/messages
- Amazon Bedrock (Claude): https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-claude.htmlSophia Ponte
02/19/2026, 6:52 PMNate
02/19/2026, 7:01 PM