Skill Packs
ThinkWork implements the Agent Skills specification — an open standard for portable, agent-readable skill definitions. A skill pack is a directory containing a SKILL.md file (with optional scripts/, references/, and assets/ directories) that defines tools, instructions, and context for managed agents.
Skill packs are stored in S3 and loaded by AgentCore at invoke time. You don’t need to rebuild or redeploy the AgentCore Lambda to add new skills — upload a skill pack and assign it to an agent.
How it works
Section titled “How it works”1. Author a skill folder with `SKILL.md`2. Upload the folder to S3: `tenants/<tenant-slug>/skill-catalog/<skill-slug>/`3. Install the skill from the admin Skills tab4. The install copies the folder into the target workspace at `skills/<skill-slug>/`5. At invoke time: AgentCore syncs the workspace, parses `SKILL.md`, and registers the skillDirectory structure
Section titled “Directory structure”A skill follows the Agent Skills directory structure:
my-skill/├── SKILL.md # Required: metadata + instructions├── scripts/ # Optional: executable code├── references/ # Optional: additional documentation├── assets/ # Optional: templates, data files└── skill.yaml # Optional: ThinkWork catalog metadataThe only required file is SKILL.md. The skill.yaml file is a ThinkWork extension for catalog metadata (display name, icon, category, triggers).
SKILL.md format
Section titled “SKILL.md format”Per the Agent Skills spec, SKILL.md has YAML frontmatter followed by markdown content.
Minimal example
Section titled “Minimal example”---name: my-skilldescription: What this skill does and when to use it.---
Your instructions here.Full example
Section titled “Full example”Here’s a Jira skill with all sections:
Instructions section — injected into the system prompt:
## Instructions
You have access to Jira. When a user asks about issues, tickets, or tasks,use the Jira tools to look up real data instead of guessing. Always includethe issue key (e.g., ENG-1234) when referencing issues.Tools section — Python functions exposed as agent tools:
## Tools
import httpximport os
JIRA_BASE_URL = os.environ["JIRA_BASE_URL"]JIRA_TOKEN = os.environ["JIRA_TOKEN"]JIRA_EMAIL = os.environ["JIRA_EMAIL"]
def search_issues(jql: str, max_results: int = 20) -> dict: """ Search Jira issues using JQL.
Args: jql: JQL query string (e.g., 'project=ENG AND status=Open') max_results: Maximum number of results to return (default 20, max 100)
Returns: dict with 'issues' list, each containing id, key, summary, status, assignee """ response = httpx.get( f"{JIRA_BASE_URL}/rest/api/3/search", headers={ "Authorization": f"Basic {JIRA_EMAIL}:{JIRA_TOKEN}", "Content-Type": "application/json" }, params={"jql": jql, "maxResults": max_results} ) response.raise_for_status() data = response.json() return { "issues": [ { "id": issue["id"], "key": issue["key"], "summary": issue["fields"]["summary"], "status": issue["fields"]["status"]["name"], "assignee": issue["fields"].get("assignee", {}).get("displayName", "Unassigned") } for issue in data["issues"] ] }
def create_issue(project_key: str, summary: str, description: str, issue_type: str = "Task") -> dict: """ Create a new Jira issue.
Args: project_key: Jira project key (e.g., 'ENG') summary: Issue title/summary description: Issue description (plain text) issue_type: Issue type (Task, Bug, Story, Epic) — defaults to Task
Returns: dict with 'id', 'key', and 'url' of the created issue """ response = httpx.post( f"{JIRA_BASE_URL}/rest/api/3/issue", headers={ "Authorization": f"Basic {JIRA_EMAIL}:{JIRA_TOKEN}", "Content-Type": "application/json" }, json={ "fields": { "project": {"key": project_key}, "summary": summary, "description": { "type": "doc", "version": 1, "content": [{"type": "paragraph", "content": [{"type": "text", "text": description}]}] }, "issuetype": {"name": issue_type} } } ) response.raise_for_status() data = response.json() return { "id": data["id"], "key": data["key"], "url": f"{JIRA_BASE_URL}/browse/{data['key']}" }Context section — static text injected into every turn’s context window:
## Context
Supported Jira issue types: Task, Bug, Story, Epic, SubtaskValid JQL operators: =, !=, IN, NOT IN, ~, IS, IS NOT, <, >, <=, >=Common JQL fields: project, status, assignee, reporter, priority, labels, created, updatedSection reference
Section titled “Section reference”| Section | Required | Purpose |
|---|---|---|
# <name> + description | Yes | Skill name and one-line description. The name is used as the skill ID. |
## Instructions | No | Text injected into the system prompt for this skill. Keep it concise — this is added to every turn. |
## Tools | No | Python code block defining functions. Each def with a docstring becomes a tool. |
## Context | No | Static text injected into the context window on every turn. Good for reference tables, enum values, and constants. |
Environment variables in tools
Section titled “Environment variables in tools”Tools run inside the AgentCore Lambda container. They have access to environment variables set on the Lambda function. Use this for credentials and configuration:
import os
JIRA_TOKEN = os.environ["JIRA_TOKEN"] # Set on AgentCore LambdaJIRA_BASE_URL = os.environ["JIRA_BASE_URL"]Set Lambda environment variables via Terraform:
# In your terraform.tfvars or a .tfvars override:agentcore_environment = { JIRA_BASE_URL = "https://yourorg.atlassian.net" JIRA_EMAIL = "bot@yourorg.com" JIRA_TOKEN = "your-api-token"}For sensitive values, use Secrets Manager and fetch at cold start:
import boto3import json
_secrets_client = boto3.client("secretsmanager")_jira_secret = None
def _get_jira_secret(): global _jira_secret if _jira_secret is None: response = _secrets_client.get_secret_value(SecretId="thinkwork/jira-credentials") _jira_secret = json.loads(response["SecretString"]) return _jira_secretUploading a skill pack
Section titled “Uploading a skill pack”# Get the workspace bucket nameBUCKET=$(thinkwork outputs -s dev --key bucket_name)
# Upload a complete skill folder for one tenantaws s3 sync ./jira/ "s3://$BUCKET/tenants/acme/skill-catalog/jira/"The skill is immediately available in that tenant’s admin Skills catalog — no Lambda redeployment needed. A user-facing zip upload is not required for the current catalog path; operators upload or edit the folder contents in the tenant catalog, then install from the Skills tab.
Assigning skills to agents
Section titled “Assigning skills to agents”Open the admin Agent page, switch to Skills, and run Add Skill for the catalog folder. Installation copies the catalog folder into the target workspace as skills/<skill-slug>/ and writes .catalog-ref.json so stale/orphan status can be detected later.
Skill IDs correspond to the tenant catalog folder name: tenants/acme/skill-catalog/jira/ → skill ID jira.
Listing available skills
Section titled “Listing available skills”Use the admin Agent Skills tab to browse tenant catalog folders and installed workspace folders. The catalog view maps directly to tenants/<tenant-slug>/skill-catalog/<skill-slug>/; the workspace view maps to installed skills/<skill-slug>/ folders.
Skill loading at invoke time
Section titled “Skill loading at invoke time”When AgentCore receives a message for an agent with installed skill packs:
- Syncs the agent workspace from S3 into
/tmp/workspace - Discovers installed skill folders under
skills/<slug>/ - Parses each
SKILL.md - Registers tools with the Strands agent loop
- Appends skill guidance through the AgentSkills progressive-disclosure plugin
The total latency depends on the number and size of installed workspace skill folders and the workspace sync cache state.
Example skill pack library
Section titled “Example skill pack library”The examples/skill-pack/ directory in the ThinkWork repo contains ready-to-use skill packs:
| Skill | Description |
|---|---|
github.md | Search issues, PRs, and code. Create issues and comments. |
jira.md | Search and create Jira issues. Transition issue status. |
confluence.md | Search Confluence pages. Create and update pages. |
slack.md | Post messages and look up channel history. |
sql.md | Run read-only SQL queries against the Aurora database. |
calculator.md | Math and unit conversion tools. |
datetime.md | Date parsing, formatting, and timezone conversion. |
http.md | Make HTTP requests to external APIs. |