
Kiro Crew Under the Hood: A Platform Engineer's Field Guide to AWS's Always-On AI Agent
Most "always-on AI agent" pitches fall apart the moment you ask an operational question. Where does state live? What happens when the box reboots? Who's allowed to message it? What stops it from running cat ~/.aws/credentials on a bad day?
Kiro Crew — AWS's open-source (Apache 2.0) agent workspace that grew out of an internal Amazon project called MeshClaw — is worth a closer look precisely because its docs answer those questions instead of dodging them.
The one-sentence version: a normal AI coding assistant forgets everything when you close the tab; Crew is a persistent runtime that keeps working — on a schedule, in the background, across restarts — and remembers what you taught it. Concretely, it's a Gateway process (default
http://localhost:5476) that fronts the kiro-cli agent, holds sessions, memory, schedules, and task checkpoints, and fans the same runtime out to Slack, Discord, Telegram, Teams, Webex, WeCom, WeChat, and the CLI.I read the whole Crew doc set — Chat, Capabilities, Features, Interfaces, Apps, Configuration, Security — the way I'd read a system I was about to put in front of a team. Here's the teardown, in plain language up top and architect-level detail underneath, with working examples. Some are lifted from the official docs; several are my own.
The mental model: one Gateway, many surfaces
Get the shape right first, because everything hangs off it:
- The Gateway is the single runtime and the single security chokepoint. Every message and every tool call passes through it. It persists session state, injects memory and skills, starts scheduled work, coordinates sub-agents, brokers approvals, and enforces policy.
- State is local and portable. Config, memory, credentials, and app files all live under
~/.kiro/crew/(override withKIROCREW_HOME). Run it on your Mac, in a container, or on a remote host you control. - Surfaces are just transports. A dashboard conversation or a Slack thread each map to an isolated session. Sessions preserve context and run concurrently.
"One runtime, many doors" is what makes the security model tractable — there's exactly one place to enforce policy.
Agent Capabilities: what you're actually configuring
New to this? "Capabilities" is just the set of dials that decide what the agent knows and what it's allowed to touch. Crew's map onto patterns you already know:
- Agents & agent templates — an agent is a saved config bundle: which model, which system prompt, which tools, which integrations. Templates are pre-built bundles you clone and tweak, so you're not starting from a blank file.
- MCP integrations — MCP (Model Context Protocol) is an open standard for plugging external tools and services into an AI agent. Add an MCP server and the agent gains new actions it can call (query a database, open a ticket, hit an internal API).
- Skills — reusable markdown instruction files (a deployment runbook, a code-review checklist, a data-pipeline guide) that the agent loads only when a task calls for it, instead of you re-explaining the process every session. Think "lazy-loaded team knowledge."
- Steering — workspace-level rules every session inherits automatically. This is your always-on house style / global policy layer.
- Hooks — automated reactions to events: run a script or inject context when something triggers (a session starts, a file changes).
- Prompts — the underlying system prompts that shape behaviour, exposed so you can edit them.
If you squint: steering = global config, skills = lazy-loaded modules, hooks = event handlers. Familiar decomposition is what makes a system operable. (Bonus: an existing
.kiro config — steering files, skills, custom agents — carries over automatically.)
Chat: a session, not a text box
If you've used any AI chat, this looks familiar — but each "chat" here is really a sandboxed workspace with real tool access, not just a conversation. Every tab is an independent session that can read/write files, run commands, browse the web, and call any configured MCP tool. Worth knowing:
- Prompt optimizer (
Cmd+Shift+Enter) rewrites a rough prompt into a sharper one before you send it — useful when you're not sure how to phrase a task. - Voice — configurable speech-to-text and text-to-speech.
- Artifacts / rich output — structured results render as widgets, not walls of text.
The mental shift: a "chat" here is an execution context with a transcript, which is exactly what lets scheduled jobs and sub-agents run as first-class sessions rather than background hacks.
Features: what it does beyond chat
This is the "always-on" part — the things that keep running when you've closed your laptop.
| Feature | Plain-language version |
|---|---|
| Sub-agents | Splits a big task into parallel helpers that work at once, then merges their answers |
| Scheduling (cron) | Recurring jobs and monitors that run on a clock or a trigger, each in its own session |
| Task Runner | Hand it a spec and walk away — it plans, executes, tests, retries, and saves progress |
| Multi-instance | Drive several remote Crew installs from one hub over SSH tunnels |
| Memory | Auto-remembers preferences, history, and lessons across sessions |
| Knowledge | A reference library of docs/folders/URLs you feed it to consult |
| Snapshot & restore | Back up everything it knows into one portable file — audit log included |
Two things matter to operators. Checkpointing means a long autonomous job survives a Gateway restart instead of starting over. And Snapshot & restore treats the agent's entire brain — memory, lessons, schedules, audit trail — as a portable artifact you can back up, migrate, and recover. That's the line between a toy and a system.
Heartbeat example (a "heartbeat" is a recurring check-in that only pings you when something's wrong), straight from chat:
1
2
3
4
Every 5 minutes, curl https://staging.internal/health.
If it returns anything other than 200, or takes over 2s,
DM me on Telegram with the status code and latency.
Otherwise stay quiet. Log every check either way.
Crew registers that as a scheduled heartbeat in its own session — it runs whether or not anyone's at the dashboard, routes to the surface you named, and logs every run. A monitor that lives in the runtime, not in your terminal.
Sub-agent fan-out, one line: "Compare Karpenter, Cluster Autoscaler, and the in-tree scheduler for our bursty EKS CI fleet — cold-start, cost under spiky load, blast radius — and recommend one." Three isolated helpers, one synthesized answer; a dead doc link in one doesn't poison the others.
Artifacts: versioned output with a deploy button
An "artifact" is any real deliverable the agent produces — a report, a static site, a small service — that Crew keeps and versions instead of losing in the chat scroll. What makes them interesting for a platform engineer: version history, live previews, and one-click deploy to your own AWS account — not an AWS-managed control plane, your account.
That separation is the architecturally clean part. The runtime is yours, the deploy target is yours, and the artifact carries its own version history so you can preview or roll back.
Where I'd use it: have a scheduled job generate an internal status dashboard, version it as an artifact, and deploy it to an S3/CloudFront target in a sandbox account — with the deploy step sitting behind an approval gate (below), so nothing reaches your account without a human nod. The version history becomes your "what did we publish, and when" trail.
Interfaces: every channel is a locked door
"Interfaces" are just the ways you reach Crew — the app, the web dashboard, the CLI, and seven chat platforms. The architect's point: each channel is an authorization boundary, not a notification sink.
- Every channel is deny-by-default and owner-locked. Slack pins to a single owner (
KIROCREW_OWNER_ID); Discord, Telegram, Teams, Webex, WeCom, WeChat use allowlists of user IDs/emails. An empty allowlist means nobody. Unauthorized messages are silently dropped and logged. - Each Slack thread is its own isolated session with full tool access, so teammates can work in parallel against the same runtime and memory.
- Telegram is the firewall-friendly one — Crew reaches out to it, so there's nothing inbound to expose; handy behind a corporate firewall. DMs only, never groups.
- The dashboard binds to loopback by default. Exposing it over a network needs token auth on every request.
So "which channels do we enable" is a real access-control decision. Turning on WeChat isn't a convenience toggle — it's opening an authenticated door into a runtime that can run commands.
Apps: how you extend it (and where to be careful)

An "app" packages up extensions so you (or the community) can add capability to Crew without forking it. An app can contribute any subset of: agents, skills, MCP servers, cron jobs, dashboard UI pages, backend processes, and lifecycle hooks. A skill-only app is one file; an agent-plus-backend-plus-UI app is a whole project. (AWS ships reference apps like Issue Radar for PR/ticket triage and DevFleets for worktree management.)
Three design decisions worth calling out:
1. It's federated and git-based. Install shallow-clones the repo into
~/.kiro/crew/app-sources/{name}/, runs the build (npm run build or pip install .), then copies into ~/.kiro/crew/apps/{name}/. Crucially: symlinks pointing outside the app are dropped, and .git/node_modules/.venv are excluded. That's a supply-chain-aware copy, not a naive cp -r. Teams can add their own registries too (opt-in, searched after the built-in one).2. Third-party apps are disabled by default — you opt in under Settings → Security.
3. Backend auth is HMAC-signed, gateway-to-app. App backends are reverse-proxied at
/apps/{name}/api/*, and the gateway signs each request with X-Crew-Proxy: <timestamp>:<hmac-sha256> so the backend can verify the caller really is the gateway — no token minting, no CORS gymnastics.The honest caveat: permissions are mostly advisory today
Apps declare a permission block in
app.json (this says what the app claims it needs):1
2
3
4
5
6
7
8
9
10
{
"permissions": {
"api": ["/api/crons", "/api/status"],
"events": ["notification", "slots"],
"mcpTools": ["cron_add", "cron_list"],
"storage": true,
"cron": true,
"network": false
}
}
The docs are refreshingly straight here: only
permissions.api is actually enforced today (deny-by-default on out-of-scope paths). The rest — events, mcpTools, storage, cron, network — are advisory and not yet enforced in-process. Full enforcement is on the roadmap.For a platform architect that's the single most important line on the page:
network: false in a third-party manifest is a promise, not a control, right now. Treat app vetting as a human process and lean on the OS sandbox and denied-commands (below) as your real boundary until in-process enforcement lands.Minimal agent-only app — a small, reviewable unit with a deliberately narrow declared surface:
1
2
3
4
5
6
7
{
"name": "oncall-triage",
"minCrewVersion": "1.0.0",
"agents": ["agents/triage.json"],
"skills": ["skills/ticket-analysis"],
"permissions": { "api": ["/api/status"], "network": false }
}
Configuration: three ways in, one source of truth
You can configure Crew from a settings UI, a CLI, or by editing a JSON file — all three write the same file, so nothing gets out of sync. Everything lands in
~/.kiro/crew/config.json.1
2
3
kirocrew config get agent.sandbox # read one key
kirocrew config set dashboard.bot_name "Ops" # write (auto-restarts the pool)
kirocrew config edit # open in $EDITOR
A representative config:
1
2
3
4
5
{
"agent": { "provider": "acp", "approval_mode": "interactive", "sandbox": "auto" },
"session": { "timeout_secs": 1800, "pool_size": 2 },
"dashboard": { "bot_name": "Crew" }
}
The operationally important separations:
- Secrets are not in
config.json. Channel tokens live in~/.kiro/crew/.env, enforced at mode 600 (owner-only read/write). Config and credentials are deliberately split. - Two things live in env vars because they can't live in config:
KIROCREW_HOME(data dir) andKIROCREW_PORT(default5476). - Setting a value auto-restarts the session pool, so there's no stale-config ambiguity.
The 600-mode
.env and the secret/config split are small details that signal someone thought about the threat model, not just the happy path.Security: the part that makes it deployable

This is the section that decides whether you can actually let an agent run commands on real infrastructure. Crew's answer: every tool call passes through an ordered pipeline, and the destructive-operation checks run before the approval prompt — so you can't accidentally "yes" your way past them.
The eight-stage gate, in order:
- Owner lock — the channel rejects unauthorized users before the message reaches a session.
- Denied commands — 137 built-in patterns block destructive ops, checked before asking for approval.
- Governance ceiling — Policy ∩ Profile, tightest-wins; the agent/app cannot loosen it.
- Sensitive path blocking — credential directories/files are invisible to tool calls.
- Tool approval — interactive review, trust escalation, or Autopilot (only fires after deny checks pass).
- Input validation — schema checks, types, length limits, unicode normalization.
- OS sandbox — process-level filesystem isolation via Linux namespaces or macOS Seatbelt.
- Output redaction — credential patterns scrubbed before anything reaches a chat surface.
A signed audit log records every decision at every step — cross-cutting, not a stage you can skip.
Sandbox modes
A "sandbox" here hides your credential folders from the agent's subprocesses so a rogue command can't read them.
| Mode | Hidden | Accessible | Best for |
|---|---|---|---|
| auto (default) | .gnupg, .gcloud, .azure, .docker | .aws, .ssh, .kube | Most users — git-over-SSH + AWS CLI still work |
| strict | above + .aws, .ssh, .kube | only ~/.ssh/known_hosts | Locked-down deployments |
| off | nothing | everything | When you understand the trade-off |
Linux uses user/mount namespaces; macOS uses Seatbelt. Windows has no equivalent OS layer — and Crew fails closed there: agent subprocesses are refused rather than run unconfined, unless you explicitly set the
sandbox_allow_unsandboxed_exec opt-in. Fail-closed on the unprotected platform is the right default, but plan around it for a Windows fleet.Denied commands — enforced at the gate, not in agent config
137 patterns, and the examples tell you the threat model:
rm -rf / and rm -rf ~; git push to protected branches; cat ~/.aws/credentials and cat ~/.ssh/id_rsa; curl 169.254.169.254 (the IMDS/SSRF credential-theft classic); aws ec2 terminate-instances, cdk destroy, DROP TABLE; echo $AWS_SECRET*.The critical line: these are enforced at Crew's own tool gate, not inside the agent config. Editing a
kiro-cli agent config cannot weaken them. That's the right place for the boundary — below the layer the agent can influence.Tool approval levels
"Approval" is the human-in-the-loop step before the agent runs a tool. Interactive (default, every call prompts) → Trust this command (session-scoped, exact tool+args) → Trust this tool (session-scoped, any args) → Autopilot (all tools auto-approved this session). Autopilot removes the human gate but deny rules and sensitive-path blocks still apply. Use it sparingly.
Governance: the enterprise ceiling
For teams, "governance" lets an admin set a hard ceiling that individual sessions can tighten but never loosen. Two composable files, tightest-wins: Policy (enterprise ceiling,
security_policy.json) and Profile (per-surface narrowing, profiles/). Effective = Policy ∩ Profile.1
2
kirocrew policy show # effective policy
kirocrew policy explain # how a given tool call would be evaluated
That
policy explain is the one I'd bake into onboarding — asking "would this call be allowed, and why?" before it runs is exactly the introspection an approval workflow needs.A locked-down profile for a shared Slack surface — read-and-report only, tighter sandbox, even though my own direct policy is broader:
1
2
3
4
5
6
7
8
9
10
11
{
"name": "slack-readonly",
"sandbox": "strict",
"approval_mode": "interactive",
"denied_extra": [
"terraform apply",
"kubectl (delete|apply|scale)",
"aws (.*)(create|delete|update|put|terminate)"
],
"tools": { "allow": ["fs_read", "execute_bash", "web_search"], "deny": ["fs_write"] }
}
Because effective scope is the intersection, this profile can only ever subtract from what enterprise policy permits. The Slack surface gets the narrower set; my dashboard session keeps the broader one. One ceiling, many narrower doors, and no door can widen it.
Credential protection, briefly
Three levels: sensitive paths blocked from tool calls; output redaction (AWS keys, private-key headers, Slack/GitHub tokens, DB connection URIs, 15+ patterns); and environment scrubbing of sensitive vars from subprocesses.
The architect's verdict
Reading Crew as infrastructure rather than a chatbot, three things stand out.
Genuinely good: the layered, ordered security pipeline with deny-before-approve; tightest-wins governance; state as a portable, snapshottable artifact; per-channel owner locks; and docs honest about what's enforced versus aspirational.
Watch: app permissions beyond
api are advisory today, so third-party app vetting is a human job right now. Windows has no OS sandbox (it fails closed, which is correct, but limits you). Autopilot quietly removes the human gate. And the whole thing runs on the proprietary, credit-metered kiro-cli at launch — the runtime is open source, the inference isn't free.Where I'd start: sandbox
auto (or strict for anything shared), a governance profile on every non-personal surface, third-party apps off until reviewed, deploy steps behind approval gates, and kirocrew policy explain in the team runbook.Crew's design philosophy is the one I trust: put the boundary below the layer the agent can influence, make state portable, and be honest in the docs about where enforcement stops. That last one is rarer than it should be.
Sources: Kiro Crew documentation (kiro.dev/docs/crew — Quick Start, Chat, Agent Capabilities, Features, Artifacts, Interfaces, Apps, Configuration, Security; pages updated August 4, 2026) and the KiroCrew GitHub repo for sandbox/Gateway internals. Example manifests and profiles are my own, written to illustrate the documented models — verify model strings and field names against current docs before shipping.
About the author
Ashish Kasaudhan is a DevSecOps Architect at Giesecke+Devrient (G+D) with 17 years in DevOps and platform engineering. His work centers on cloud infrastructure, containerization, CI/CD, and enterprise automation, with a growing focus on where AIOps and MLOps meet day-to-day platform work. He's a member of the AWS Community Builders program.
He writes practitioner-grade breakdowns of cloud and DevOps tooling — the kind that go past the marketing surface to how a thing actually behaves in production. Connect on LinkedIn .
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article