Enforce actor-level MCP policy wiring and Claude tool gates
This commit is contained in:
93
README.md
93
README.md
@@ -11,11 +11,13 @@ TypeScript runtime for deterministic multi-agent execution with:
|
||||
- Resource provisioning (git worktrees + deterministic port ranges)
|
||||
- MCP configuration layer with handler policy hooks
|
||||
- Security middleware for shell/tool policy enforcement
|
||||
- Runtime event fan-out (NDJSON analytics log + optional Discord webhook notifications)
|
||||
|
||||
## Architecture Summary
|
||||
|
||||
- `SchemaDrivenExecutionEngine.runSession(...)` is the single execution entrypoint.
|
||||
- `PipelineExecutor` owns runtime control flow and topology dispatch while delegating failure classification and persistence/event side-effects to dedicated policies.
|
||||
- Runtime events are emitted as best-effort side-channel telemetry and do not affect orchestration control flow.
|
||||
- `AgentManager` is an internal utility used by the pipeline when fan-out/retry-unrolled behavior is required.
|
||||
- Session state is persisted under `AGENT_STATE_ROOT`.
|
||||
- Project state is persisted under `AGENT_PROJECT_CONTEXT_PATH` with schema-versioned JSON (`schemaVersion`) and domains:
|
||||
@@ -39,6 +41,7 @@ TypeScript runtime for deterministic multi-agent execution with:
|
||||
- `provisioning.ts`: resource provisioning and child suballocation helpers
|
||||
- `src/mcp`: MCP config types/conversion/handlers
|
||||
- `src/security`: shell AST parsing, rules engine, secure executor, and audit sinks
|
||||
- `src/telemetry`: runtime event schema, sink fan-out, file sink, and Discord webhook sink
|
||||
- `src/examples`: provider entrypoints (`codex.ts`, `claude.ts`)
|
||||
- `src/config.ts`: centralized env parsing/validation/defaulting
|
||||
- `tests`: manager, manifest, pipeline/orchestration, state, provisioning, MCP
|
||||
@@ -101,6 +104,78 @@ Actors can emit events in `ActorExecutionResult.events`. Pipeline status also em
|
||||
- session closure aborts child recursive work
|
||||
- run summaries expose aggregate `status`: success requires successful terminal executed DAG nodes and no critical-path failure
|
||||
|
||||
## Runtime Events
|
||||
|
||||
- The pipeline emits runtime lifecycle events (`session.started`, `node.attempt.completed`, `domain.*`, `session.completed`, `session.failed`).
|
||||
- Runtime events are fan-out only and never used for edge-routing decisions.
|
||||
- Default sink writes NDJSON to `AGENT_RUNTIME_EVENT_LOG_PATH`.
|
||||
- Optional Discord sink posts high-visibility lifecycle/error events through webhook configuration.
|
||||
- Existing security command audit output (`AGENT_SECURITY_AUDIT_LOG_PATH`) remains in place and is also mirrored into runtime events.
|
||||
|
||||
### Runtime Event Fields
|
||||
|
||||
Each runtime event is written as one NDJSON object with:
|
||||
|
||||
- `id`, `timestamp`, `type`, `severity`
|
||||
- `sessionId`, `nodeId`, `attempt`
|
||||
- `message`
|
||||
- optional `usage` (`tokenInput`, `tokenOutput`, `tokenTotal`, `toolCalls`, `durationMs`, `costUsd`)
|
||||
- optional structured `metadata`
|
||||
|
||||
### Runtime Event Setup
|
||||
|
||||
Add these variables in `.env` (or use defaults):
|
||||
|
||||
```bash
|
||||
AGENT_RUNTIME_EVENT_LOG_PATH=.ai_ops/events/runtime-events.ndjson
|
||||
AGENT_RUNTIME_DISCORD_WEBHOOK_URL=
|
||||
AGENT_RUNTIME_DISCORD_MIN_SEVERITY=critical
|
||||
AGENT_RUNTIME_DISCORD_ALWAYS_NOTIFY_TYPES=session.started,session.completed,session.failed
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- File sink is always enabled and appends NDJSON.
|
||||
- Discord sink is enabled only when `AGENT_RUNTIME_DISCORD_WEBHOOK_URL` is set.
|
||||
- Discord notifications are sent when event severity is at or above `AGENT_RUNTIME_DISCORD_MIN_SEVERITY`.
|
||||
- Event types in `AGENT_RUNTIME_DISCORD_ALWAYS_NOTIFY_TYPES` are always sent, regardless of severity.
|
||||
|
||||
### Event Types Emitted by Runtime
|
||||
|
||||
- Session lifecycle:
|
||||
- `session.started`
|
||||
- `session.completed`
|
||||
- `session.failed`
|
||||
- Node/domain lifecycle:
|
||||
- `node.attempt.completed`
|
||||
- `domain.<domain_event_type>` (for example `domain.validation_failed`)
|
||||
- Security mirror events:
|
||||
- `security.shell.command_profiled`
|
||||
- `security.shell.command_allowed`
|
||||
- `security.shell.command_blocked`
|
||||
- `security.tool.invocation_allowed`
|
||||
- `security.tool.invocation_blocked`
|
||||
|
||||
### Analytics Quick Start
|
||||
|
||||
Inspect latest events:
|
||||
|
||||
```bash
|
||||
tail -n 50 .ai_ops/events/runtime-events.ndjson
|
||||
```
|
||||
|
||||
Count events by type:
|
||||
|
||||
```bash
|
||||
jq -r '.type' .ai_ops/events/runtime-events.ndjson | sort | uniq -c
|
||||
```
|
||||
|
||||
Get only critical events:
|
||||
|
||||
```bash
|
||||
jq -c 'select(.severity=="critical")' .ai_ops/events/runtime-events.ndjson
|
||||
```
|
||||
|
||||
## Security Middleware
|
||||
|
||||
- Shell command parsing uses async `sh-syntax` (WASM-backed mvdan/sh parser) with fail-closed command/redirect extraction.
|
||||
@@ -117,6 +192,8 @@ Actors can emit events in `ActorExecutionResult.events`. Pipeline status also em
|
||||
- optional uid/gid drop
|
||||
- stdout/stderr streaming hooks for audit
|
||||
- Every actor execution input now includes `security` helpers (`rulesEngine`, `createCommandExecutor(...)`) so executors can enforce shell/tool policy at the execution boundary.
|
||||
- Every actor execution input now includes `mcp` helpers (`registry`, `resolveConfig(...)`) so MCP server config resolution stays centrally policy-controlled per persona/tool-clearance.
|
||||
- For Claude-based executors, use `input.mcp.createClaudeCanUseTool()` as the SDK `canUseTool` callback to enforce persona allowlist/banlist before each tool invocation.
|
||||
- Pipeline behavior on `SecurityViolationError` is configurable:
|
||||
- `hard_abort` (default)
|
||||
- `validation_fail` (retry-unrolled remediation)
|
||||
@@ -127,6 +204,7 @@ Actors can emit events in `ActorExecutionResult.events`. Pipeline status also em
|
||||
|
||||
- `CODEX_API_KEY`
|
||||
- `OPENAI_API_KEY`
|
||||
- `OPENAI_AUTH_MODE` (`auto`, `chatgpt`, or `api_key`)
|
||||
- `OPENAI_BASE_URL`
|
||||
- `CODEX_SKIP_GIT_CHECK`
|
||||
- `CLAUDE_CODE_OAUTH_TOKEN` (preferred for Claude auth; takes precedence over `ANTHROPIC_API_KEY`)
|
||||
@@ -171,6 +249,13 @@ Actors can emit events in `ActorExecutionResult.events`. Pipeline status also em
|
||||
- `AGENT_SECURITY_DROP_UID`
|
||||
- `AGENT_SECURITY_DROP_GID`
|
||||
|
||||
### Runtime Events / Telemetry
|
||||
|
||||
- `AGENT_RUNTIME_EVENT_LOG_PATH`
|
||||
- `AGENT_RUNTIME_DISCORD_WEBHOOK_URL`
|
||||
- `AGENT_RUNTIME_DISCORD_MIN_SEVERITY` (`info`, `warning`, or `critical`)
|
||||
- `AGENT_RUNTIME_DISCORD_ALWAYS_NOTIFY_TYPES` (CSV event types such as `session.started,session.completed,session.failed`)
|
||||
|
||||
### Runtime-Injected (Do Not Configure In `.env`)
|
||||
|
||||
- `AGENT_REPO_ROOT`
|
||||
@@ -183,6 +268,14 @@ Actors can emit events in `ActorExecutionResult.events`. Pipeline status also em
|
||||
|
||||
Defaults are documented in `.env.example`.
|
||||
|
||||
Auth behavior notes:
|
||||
|
||||
- OpenAI/Codex:
|
||||
- `OPENAI_AUTH_MODE=auto` (default) prefers API keys when configured, and otherwise relies on existing Codex CLI login (`codex login` / ChatGPT plan auth).
|
||||
- `OPENAI_AUTH_MODE=chatgpt` always omits API key injection so Codex uses ChatGPT subscription auth/session.
|
||||
- Claude:
|
||||
- If `CLAUDE_CODE_OAUTH_TOKEN` and `ANTHROPIC_API_KEY` are both unset, runtime auth options are omitted and Claude Agent SDK can use existing Claude Code login state.
|
||||
|
||||
## Quality Gate
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user