Deployment
Two independent deploy paths: CDK for the AgentCore runtime, SAM for the Lambda application. Neither depends on the other at deploy time.
Order for a fresh environment
-
Deploy the SAM stack. It creates the shared secret (
agentcore-configs) as an empty resource, the queues, and the functions. -
Populate the secret — see the shared secret. Functions will fail their cold start until it is populated.
-
Apply the BigQuery views from
bigquery/*.sql. Handlers that query a missing view log the error and return. -
Deploy the CDK stack for the AgentCore runtime.
-
Force a cold start on the Lambdas so they pick up the populated secret (redeploy, or touch the function configuration).
SAM — Lambda application
Run from lambdas/.
make deploy # sync all requirements → sam build --no-cached → sam deploy
Per-function deploys build only that resource, then deploy the stack; CloudFormation applies only what changed:
make deploy-scraper
make deploy-scorer
make deploy-hubspot
make deploy-email-agent
make deploy-phone-agent
Each target first regenerates requirements.txt from uv.lock:
cd <function> && uv export --no-dev --no-hashes -o requirements.txt
|
A dependency added with |
Stack settings come from lambdas/samconfig.toml: stack name morpheus-sam,
CAPABILITY_IAM, resolve_s3 = true, confirm_changeset = false. Resource
names are derived from the stack name, so the CRM queue is
morpheus-sam-crm-sync.fifo and the CRM function is morpheus-sam-hubspot-sync.
Useful outputs:
aws cloudformation describe-stacks \
--stack-name morpheus-sam \
--query "Stacks[0].Outputs" --output table
AgentcoreSecretArn, CrmSyncQueueUrl, EnrichmentPipelineQueueUrl,
CrmSyncDlqUrl, EnrichmentPipelineDlqUrl, and one ARN + IAM role per function.
CDK — AgentCore runtime
Run from the repository root.
make deploy-cdk # cdk bootstrap (idempotent) + cdk deploy --all
make deploy-dev # cdk deploy --all
make deploy-prod # cdk deploy --all --require-approval never
Or from cdk/:
pnpm install
npx cdk diff # review before applying
npx cdk deploy
Requires a running Docker daemon: the stack builds the agentcore/ image for
linux/arm64 via DockerImageAsset and pushes it to ECR.
The secret ARN is currently hardcoded in cdk/bin/cdk.ts. Update it when the
secret is recreated.
Outputs: AgentRuntimeId, AgentRuntimeArn, RuntimeRoleArn, ImageUri,
LogGroupName, and SecretArn. Copy RuntimeRoleArn into
agentcore/.bedrock_agentcore.yaml as execution_role so the AgentCore CLI uses
the CDK-managed role rather than creating its own.
Details: CDK stack.
BigQuery views
There is no migration runner. Apply a changed view by executing its file:
bq query --use_legacy_sql=false < bigquery/v_lost_deal_reeng.sql
Views are CREATE OR REPLACE, so re-applying is safe. The handler queries are
pinned to view names in lambdas/morpheus_hubspot/utils/constants.py and
lambdas/phone_agent/utils/constants.py — renaming a view requires a code
change and a Lambda deploy.
See BigQuery views.
Verifying a deploy
# Tail a function
aws logs tail /aws/lambda/morpheus-sam-hubspot-sync --follow
# Tail the runtime
aws logs tail /aws/bedrock-agentcore/agents/agentcore --follow
# Confirm nothing landed in a DLQ
aws sqs get-queue-attributes \
--queue-url <CrmSyncDlqUrl> \
--attribute-names ApproximateNumberOfMessages
Trigger a scheduled handler on demand rather than waiting for its rule:
aws lambda invoke \
--function-name morpheus-sam-hubspot-sync \
--payload '{"detail-type":"Hubspot.ContactResolve","source":"morpheus.hubspot","detail":{}}' \
--cli-binary-format raw-in-base64-out /dev/stdout
Enabling a disabled trigger
Several schedules and the EnrichmentPipelineQueue SQS trigger are commented out
in lambdas/template.yaml — see EventBridge
schedules for the current state of each. To enable one, uncomment the Events
block and redeploy. Two constraints:
-
An SQS-triggered function’s
Timeoutmust stay below the queue’sVisibilityTimeout. -
The
InputJSONdetail-typemust exactly match a key registered in that function’sregistry.py, or the handler logs "no handler registered" and returns.