Skip to content

Getting Started

This guide is for self-hosting the open Agent Harness in your own AWS account — the leftmost door of the three-tier deployment ladder (ThinkWork open / ThinkWork for Business / ThinkWork Enterprise). Everything deploys entirely into your AWS account. No SaaS control plane, no shared infrastructure, no black-box hosted harness. The code runs in your VPC, data lives in your Aurora database, and models run through your Bedrock endpoint.

This guide walks you from zero to a running agent invoke. The point is not that ThinkWork is powerful — it is that a production-grade Agent Harness can be straightforward to deploy without surrendering ownership of the runtime. If you’d rather not run the runtime yourself, the same harness is operated by us as ThinkWork for Business; start there instead.

Before you start, make sure you have:

  • AWS account with the ability to create IAM roles, Lambda functions, Aurora clusters, and AppSync APIs
  • AWS credentials configured locally (~/.aws/credentials or environment variables)
  • Node.js 20+ — the CLI is distributed via npm
  • Terraform 1.6+ — the CLI shells out to terraform under the hood
  • Bedrock model access — enable at least one Claude model (e.g. anthropic.claude-3-5-sonnet-20241022-v2:0) in your target region
Terminal window
npm install -g thinkwork-cli

Confirm it installed correctly:

Terminal window
thinkwork --version
# 1.0.0

thinkwork login picks the AWS profile the CLI will use for every terraform and aws CLI shell-out. It’s an arrow-key picker over your existing ~/.aws/ profiles, with fall-through to access-key entry or aws sso login.

Terminal window
thinkwork login

The chosen profile is saved as defaultProfile in ~/.thinkwork/config.json. Subsequent commands honour it unless you override with --profile <name> per command or $AWS_PROFILE.

Terminal window
# Non-interactive variants
thinkwork login --sso --profile work-sso # aws sso login
thinkwork login --keys --profile thinkwork # enter fresh access keys

thinkwork init scaffolds a ThinkWork deployment directory with a terraform.tfvars file and a local state configuration.

Terminal window
thinkwork init -s dev

This creates a thinkwork/ directory (or uses the current directory if you’re already inside one) with:

thinkwork/
├── terraform.tfvars # Your deployment variables
├── .terraform.lock.hcl # Provider lock file (committed to git)
└── .thinkwork/ # Local CLI metadata
└── stage.json

Open terraform.tfvars and fill in the required values:

terraform.tfvars
stage = "dev"
region = "us-east-1"
account_id = "123456789012"
db_password = "change-me-before-deploy"
# Optional — defaults shown
database_engine = "aurora-serverless" # or "rds-postgres"
# enable_hindsight = true # optional Hindsight add-on (ECS+ALB)

AgentCore managed memory is always on — every agent gets automatic per-turn retention with zero config. Set enable_hindsight = true to additionally provision the Hindsight ECS service for semantic + entity-graph retrieval alongside it.

Terminal window
thinkwork deploy -s dev

This command runs terraform init followed by terraform apply inside the ThinkWork module. The first deploy provisions approximately 260 AWS resources across three tiers:

  • Foundation — VPC, subnets, Cognito user pool, KMS keys, Route53 records
  • Data — Aurora Postgres cluster, S3 buckets, Bedrock Knowledge Base
  • App — AppSync API, API Gateway, AgentCore Lambda, Step Functions, SES

A typical first deploy takes 12–18 minutes. Subsequent deploys that don’t touch the database or VPC take 2–4 minutes.

thinkwork deploy -s dev
Initializing Terraform...
Planning changes...
+ 264 resources to create
Applying... this will take ~15 minutes on first deploy.
✓ Foundation tier complete (4m 12s)
✓ Data tier complete (6m 33s)
✓ App tier complete (3m 44s)
Deploy complete. Run `thinkwork outputs -s dev` to see endpoints.

thinkwork doctor validates your deployment end-to-end. It checks that every major service is reachable and configured correctly.

Terminal window
thinkwork doctor -s dev
thinkwork doctor -s dev
Checking deployment: dev (us-east-1)
✓ Terraform state readable
✓ Aurora cluster: available
✓ Cognito user pool: active
✓ AppSync API: reachable
✓ API Gateway: reachable
✓ AgentCore Lambda: responding
✓ Bedrock model access: anthropic.claude-3-5-sonnet-20241022-v2:0
✓ S3 skill bucket: accessible
✓ SES sending: verified
All checks passed.

If any check fails, doctor prints the specific error and a remediation hint.

Before signing in, take a look at what got deployed. thinkwork outputs prints the key endpoints you’ll need — the AppSync URL, the API Gateway URL, the admin app URL, and the Cognito pool id.

Terminal window
thinkwork outputs -s dev
AppSync API URL: https://abc123.appsync-api.us-east-1.amazonaws.com/graphql
API Gateway URL: https://xyz789.execute-api.us-east-1.amazonaws.com
Admin App URL: https://app.thinkwork.dev.example.com
Cognito Pool ID: us-east-1_ABC123XYZ

Bookmark the Admin App URL — that’s your operator console. The AppSync and API Gateway URLs are what your clients (mobile app, SDKs, or custom integrations) will point at.

thinkwork login with --stage <name> signs you in to the Cognito user pool that was just provisioned. It opens your browser against Cognito’s hosted UI (Google OAuth works if you configured it in terraform.tfvars), catches the redirect on a local loopback, and stashes the id/refresh tokens in ~/.thinkwork/config.json under sessions["dev"].

Terminal window
thinkwork login --stage dev
# Opens your browser to https://thinkwork-dev.auth.us-east-1.amazoncognito.com/oauth2/authorize?…
# Sign in. The CLI catches the callback, exchanges the code, and caches your session.

Verify it worked:

Terminal window
thinkwork me
⬡ Thinkwork — me
Stage: dev
Stage dev
Mode cognito
User ID u_01HXXXYZ...
Email you@example.com
Tenant ID t_01HXXX...
Tenant slug acme

With the outputs from Step 6, you’re ready to send your first message. You can use the admin web app, a GraphQL client, or the test harness:

Terminal window
# 1. Create a thread
curl -X POST https://xyz789.execute-api.us-east-1.amazonaws.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateThread($input: CreateThreadInput!) { createThread(input: $input) { id prefix status } }",
"variables": {
"input": {
"channel": "CHAT",
"title": "My first thread"
}
}
}'
# 2. Send a message
curl -X POST https://xyz789.execute-api.us-east-1.amazonaws.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation SendMessage($input: SendMessageInput!) { sendMessage(input: $input) { id body role } }",
"variables": {
"input": {
"threadId": "CHAT-0001",
"body": "What can you help me with?"
}
}
}'