Overview
Kiro agent profiles are JSON files. Project agents live in.kiro/agents/.
User agents live in ~/.kiro/agents/.
When Observal installs a Kiro agent, it writes telemetry hooks into a standalone
hooks file — ~/.kiro/hooks/observal.json (user scope) or
.kiro/hooks/observal.json (project scope) — in the v1 schema, using the
UserPromptSubmit and Stop triggers. Both hooks run the shared
observal_cli.hooks.session_push --harness kiro entry point.
Kiro IDE 1.0 and CLI 3.0 read the standalone file; the IDE does not fire
inline agent hooks. Once installed, shared hooks collect all Kiro sessions
in that scope, including ordinary conversations using MCPs or skills. Agent
attribution is separate: sessions without a verified registry agent remain
unattributed.
Inline hooks do not hide an agent from the IDE agent picker. What does is
allowedTools or toolsSettings without a permissions block: Kiro IDE 1.x
ProfileLoader rejects such a profile outright (reasonCode cli_only_agent).
Observal no longer emits either field and strips them on pull.
Legacy Kiro CLI 2.x
Kiro CLI 2.x only understands inline agent hooks. When Observal detects CLI 2.x, it additionally writes legacy inlineuserPromptSubmit/stop hooks into
the agent JSON, even when the IDE is installed. Ordinary CLI 2.x sessions do
not fire these agent-specific hooks; use observal reconcile --harness kiro
to backfill them.
Detection can be overridden with OBSERVAL_KIRO_CLI_VERSION and
OBSERVAL_KIRO_IDE (1/0).
The hook reads Kiro CLI JSONL files from ~/.kiro/sessions/cli/ and IDE
transcripts from workspace session directories. It sends new records since the
last push. Reconciliation backfills missed CLI and IDE sessions, including
separately stored delegated sub-executions.
Supported capabilities
Setup
1. Install the Observal CLI
2. Authenticate
~/.observal/config.json.
3. Pull an agent into Kiro
~/.kiro/agents/{name}.json.
To install into the current project:
.kiro/agents/{name}.json.
4. Refresh Kiro hooks
Pull the agent again to refresh its Observal hook commands.doctor patch does not install generic Kiro hooks: pulling an agent installs
shared hooks for its scope. These hooks do not carry that agent’s UUID and
capture ordinary sessions too. CLI 2.x still needs per-agent inline hooks.
Config paths
Kiro MCP configs use the
mcpServers key.
Hook spec
Observal writes the telemetry hooks to the standalone v1 hooks file —~/.kiro/hooks/observal.json (user scope) or .kiro/hooks/observal.json
(project scope):
OBSERVAL_AGENT_ID. One file per scope serves every
agent, so an id baked into it would attribute every session to whichever agent
was pulled last. Attribution comes from session metadata instead.
On non-Windows platforms, generated server config may use python3 instead of
python. During observal agent pull, the CLI rewrites Observal hook commands to use
the active Python interpreter.
Legacy CLI 2.x inline hooks
Kiro CLI 2.x predates the standalone file and reads hooks only from the agent JSON. On a machine whosekiro-cli reports major version 2, Observal also
writes inline userPromptSubmit/stop hooks into each agent profile, carrying
OBSERVAL_AGENT_ID since an agent profile belongs to exactly one agent:
Attribution
The hooks file is shared by every agent, so the hook command cannot identify one. Attribution is resolved from the session itself:- A session started as an agent — picked from the IDE’s agent dropdown —
records that agent in
session_start.agentType, and the agent’s own profile hooks fire with an agent-scopedhookId. Either names the agent. - A session that delegates records
sub_agent_startwithsubAgentName, and the delegated agent’s work is written to a separate child transcript. The parent conversation is collected but is not attributed to the delegate. - CLI sessions carry the active agent in the session metadata written beside the transcript.
- The CLI selects the active server URL under
registriesin~/.observal/lockfile.json, then looks up that name under that registry’skiroharness. - A verified agent receives its lockfile id and version. Ordinary sessions
and unknown agents are still collected, with no agent id rather than a
guessed one. Legacy CLI 2.x inline hooks may carry
OBSERVAL_AGENT_ID.
Event map
preToolUse and postToolUse hooks can include a matcher. Observal uses *
when no matcher is set.
Session push behavior
Kiro uses the shared acknowledged session delivery engine:- Resolve the Kiro session ID from the hook payload or
~/.observal/.kiro-session. - Find
~/.kiro/sessions/cli/{session_id}.jsonlthrough the Kiro adapter. - Read complete records after the acknowledged byte/line cursor.
- Persist new batches to
~/.observal/telemetry_buffer.dbbefore network delivery. - Retry batches idempotently until the server returns a contiguous checkpoint covering them.
- Advance the local cursor only to that acknowledged checkpoint.
- Recover missing or corrupt local state from the authenticated server checkpoint.
- On finalization, compare the SHA-256 audit manifest and replay any affected range.
stop, a delayed stable-file pass captures late records and finalizes the cursor. The adapter also reads ~/.kiro/sessions/cli/{session_id}.json and durably sends Kiro credit usage, including when no transcript lines were added by the final hook.
Agent profile format
Observal generates Markdown agent profiles like this:model field is present when a model is resolved for the agent.
Skill file format
Kiro skills live at:
Example:
Caveats
Guidance files are scan-only. Observal layers Kiro steering files andAGENTS.md as context, but does not overwrite them during pull.
Hooks are per scope, not per agent. Pulling an agent refreshes the shared
observal.json hooks file for that scope, which then serves every Kiro agent
there — so the file exists even when no agent is locked. Pull the agent again
to replace an older Kiro-specific push command with the shared acknowledged
exporter. On legacy CLI 2.x, inline per-agent hooks carrying
OBSERVAL_AGENT_ID are written in addition.
Default scope is user. observal agent pull <agent-name> --harness kiro
writes to ~/.kiro/agents/ unless --scope project is set.
No Claude Code subagent layout. Kiro reads
~/.kiro/sessions/cli/{session_id}.jsonl. It does not scan Claude Code’s
subagents/ directory.
MCP config is Kiro-specific. Kiro uses .kiro/settings/mcp.json and
~/.kiro/settings/mcp.json, not Claude Code MCP paths.
