@probelabs/visor 0.1.169-ee → 0.1.170-ee

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,19 +7,20 @@
7
7
  [![Node](https://img.shields.io/badge/Node.js-18%2B-green)](https://nodejs.org/)
8
8
  [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
9
9
 
10
- Orchestrate checks, MCP tools, and AI providers with YAML-driven pipelines.
11
- Runs as GitHub Action, CLI, Slack bot, or HTTP API.
10
+ Orchestrate checks, MCP tools, AI providers, and A2A agents with YAML-driven pipelines.
11
+ Runs as GitHub Action, CLI, Slack bot, HTTP API, or A2A agent server.
12
12
  </div>
13
13
 
14
14
  ---
15
15
 
16
- Visor is an open-source workflow engine that lets you define multi-step AI pipelines in YAML. Wire up shell commands, AI providers, MCP tools, HTTP calls, and custom scripts into dependency-aware DAGs — then run them from your terminal, CI, Slack, or an HTTP endpoint.
16
+ Visor is an open-source workflow engine that lets you define multi-step AI pipelines in YAML. Wire up shell commands, AI providers, MCP tools, A2A agents, HTTP calls, and custom scripts into dependency-aware DAGs — then run them from your terminal, CI, Slack, an HTTP endpoint, or as a standards-compliant A2A agent server.
17
17
 
18
18
  **What you get out of the box:**
19
19
 
20
20
  - **YAML-driven pipelines** — define checks, transforms, routing, and AI prompts in a single config file.
21
- - **4 runtime modes** — CLI, GitHub Action, Slack bot, HTTP server — same config, any surface.
22
- - **12+ provider types** — `ai`, `command`, `script`, `mcp`, `http`, `claude-code`, `github`, `memory`, `workflow`, and more.
21
+ - **5 runtime modes** — CLI, GitHub Action, Slack bot, HTTP server, A2A agent server — same config, any surface.
22
+ - **15+ provider types** — `ai`, `a2a`, `command`, `script`, `mcp`, `http`, `claude-code`, `github`, `memory`, `workflow`, and more.
23
+ - **Agent interoperability** — A2A protocol support: expose workflows as discoverable agents, or call external A2A agents from your pipelines.
23
24
  - **AI orchestration** — multi-provider (Gemini, Claude, OpenAI, Bedrock), session reuse, MCP tool calling, retry & fallback.
24
25
  - **Execution engine** — dependency DAGs, parallel waves, forEach fan-out, conditional routing, failure auto-remediation.
25
26
  - **Built-in testing** — YAML-native integration tests with fixtures, mocks, and assertions.
@@ -34,6 +35,7 @@ Visor is an open-source workflow engine that lets you define multi-step AI pipel
34
35
  - [Provider Types](#-provider-types)
35
36
  - [Orchestration](#-orchestration)
36
37
  - [AI & MCP](#-ai--mcp)
38
+ - [Agent Protocol (A2A)](#-agent-protocol-a2a)
37
39
  - [GitHub Provider](#-github-provider)
38
40
  - [Templating & Transforms](#-templating--transforms)
39
41
  - [Suppressing Warnings](#-suppressing-warnings)
@@ -163,7 +165,7 @@ Learn more: [docs/assistant-workflows.md](docs/assistant-workflows.md) | Example
163
165
 
164
166
  ## 🖥️ Runtime Modes
165
167
 
166
- Visor runs the same YAML config across four surfaces:
168
+ Visor runs the same YAML config across five surfaces:
167
169
 
168
170
  | Mode | How to run | Best for |
169
171
  |------|-----------|----------|
@@ -171,6 +173,7 @@ Visor runs the same YAML config across four surfaces:
171
173
  | **GitHub Action** | `uses: probelabs/visor@v1` | PR reviews, issue triage, annotations |
172
174
  | **Slack bot** | `visor --slack --config .visor.yaml` | Team assistants, ChatOps |
173
175
  | **HTTP server** | `http_server: { enabled: true, port: 8080 }` | Webhooks, API integrations |
176
+ | **A2A agent** | `visor --a2a --config .visor.yaml` | Agent interoperability, multi-agent systems |
174
177
 
175
178
  Additional modes:
176
179
  - **TUI** — interactive chat-style terminal UI: `visor --tui`
@@ -185,6 +188,8 @@ visor --analyze-branch-diff # PR-style diff analysis
185
188
  visor --event pr_updated # Simulate GitHub events
186
189
  visor --tui --config ./workflow.yaml # Interactive TUI
187
190
  visor --debug-server --debug-port 3456 # Live web debugger
191
+ visor --a2a --config workflow.yaml # A2A agent server
192
+ visor tasks list --watch # Monitor A2A task queue
188
193
  visor config snapshots # Config version history
189
194
  visor validate # Validate config
190
195
  visor test --progress compact # Run integration tests
@@ -227,6 +232,7 @@ Learn more: [docs/commands.md](docs/commands.md)
227
232
  | Provider | Description | Example use |
228
233
  |----------|------------|------------|
229
234
  | `ai` | Multi-provider AI (Gemini, Claude, OpenAI, Bedrock) | Code review, analysis, generation |
235
+ | `a2a` | Call external A2A agents | Agent delegation, multi-agent workflows |
230
236
  | `command` | Shell commands with Liquid templating | Run tests, build, lint |
231
237
  | `script` | JavaScript in a secure sandbox | Transform data, custom logic |
232
238
  | `mcp` | MCP tool execution (stdio/SSE/HTTP) | External tool integration |
@@ -434,6 +440,57 @@ steps:
434
440
 
435
441
  Learn more: [docs/claude-code.md](docs/claude-code.md) · [docs/mcp-provider.md](docs/mcp-provider.md) · [docs/advanced-ai.md](docs/advanced-ai.md)
436
442
 
443
+ ## 🤝 Agent Protocol (A2A)
444
+
445
+ Visor implements the [A2A (Agent-to-Agent) protocol](https://github.com/google/A2A) for agent interoperability. Every Visor workflow can become a discoverable, standards-compliant agent — and every A2A agent in the ecosystem becomes a callable step in your workflows.
446
+
447
+ ### Server: Expose Workflows as an A2A Agent
448
+
449
+ ```yaml
450
+ agent_protocol:
451
+ enabled: true
452
+ protocol: a2a
453
+ port: 9000
454
+ agent_card_inline:
455
+ name: "Code Review Agent"
456
+ description: "AI-powered code review"
457
+ skills:
458
+ - id: security
459
+ name: Security Review
460
+ description: Analyze code for vulnerabilities
461
+ skill_routing:
462
+ security: security-review
463
+ default_workflow: general-review
464
+ auth:
465
+ type: bearer
466
+ token_env: AGENT_AUTH_TOKEN
467
+ ```
468
+
469
+ ```bash
470
+ visor --a2a --config .visor.yaml # Start A2A server on port 9000
471
+ visor tasks list --watch # Monitor task queue
472
+ ```
473
+
474
+ ### Client: Call External A2A Agents
475
+
476
+ ```yaml
477
+ steps:
478
+ compliance-scan:
479
+ type: a2a
480
+ agent_url: "http://compliance-agent:9000"
481
+ message: |
482
+ Review PR #{{ pr.number }}: {{ pr.title }}
483
+ blocking: true
484
+ timeout: 60000
485
+
486
+ summarize:
487
+ type: ai
488
+ depends_on: [compliance-scan]
489
+ prompt: "Summarize: {{ outputs['compliance-scan'] | json }}"
490
+ ```
491
+
492
+ Learn more: [docs/a2a-provider.md](docs/a2a-provider.md) · [RFC: A2A Protocol Support](rfc/001-a2a-protocol-support.md) · [Example config](examples/a2a-agent-example.yaml)
493
+
437
494
  ## 🧰 GitHub Provider
438
495
 
439
496
  Native GitHub operations (labels, comments, checks) without shelling out to `gh`:
@@ -709,7 +766,7 @@ Learn more: [docs/enterprise-policy.md](docs/enterprise-policy.md)
709
766
  [Assistant workflows](docs/assistant-workflows.md) · [CLI commands](docs/commands.md) · [Configuration](docs/configuration.md) · [AI config](docs/ai-configuration.md) · [Dependencies](docs/dependencies.md) · [forEach propagation](docs/foreach-dependency-propagation.md) · [Failure routing](docs/failure-routing.md) · [Liquid templates](docs/liquid-templates.md) · [Schema-template system](docs/schema-templates.md) · [Fail conditions](docs/fail-if.md) · [Timeouts](docs/timeouts.md) · [Execution limits](docs/limits.md) · [Output formats](docs/output-formats.md) · [Output formatting](docs/output-formatting.md) · [HTTP integration](docs/http.md) · [Scheduler](docs/scheduler.md)
710
767
 
711
768
  **Providers:**
712
- [Command](docs/command-provider.md) · [Script](docs/script.md) · [MCP](docs/mcp-provider.md) · [MCP tools for AI](docs/mcp.md) · [Claude Code](docs/claude-code.md) · [GitHub ops](docs/github-ops.md) · [Custom providers](docs/pluggable.md)
769
+ [A2A](docs/a2a-provider.md) · [Command](docs/command-provider.md) · [Script](docs/script.md) · [MCP](docs/mcp-provider.md) · [MCP tools for AI](docs/mcp.md) · [Claude Code](docs/claude-code.md) · [GitHub ops](docs/github-ops.md) · [Custom providers](docs/pluggable.md)
713
770
 
714
771
  **Operations:**
715
772
  [GitHub Action reference](docs/action-reference.md) · [Security](docs/security.md) · [Performance](docs/performance.md) · [Observability](docs/observability.md) · [Debugging](docs/debugging.md) · [Debug visualizer](docs/debug-visualizer.md) · [Troubleshooting](docs/troubleshooting.md) · [Suppressions](docs/suppressions.md) · [GitHub checks](docs/GITHUB_CHECKS.md)
@@ -766,7 +766,7 @@ steps:
766
766
  # ProbeAgent resolves "*" and "!" patterns natively.
767
767
  ai_allowed_tools_js: |
768
768
  // Start with wildcard — allow all tools by default
769
- const excluded = ['search', 'query', 'extract', 'listFiles', 'searchFiles', 'delegate'];
769
+ const excluded = ['search', 'query', 'extract', 'listFiles', 'searchFiles', 'delegate', 'analyze_all'];
770
770
  const bashEnabled = outputs['build-config']?.bash_enabled === true;
771
771
  if (!bashEnabled) {
772
772
  excluded.push('bash');
@@ -472,7 +472,7 @@ steps:
472
472
  ai:
473
473
  skip_code_context: true
474
474
  enableDelegate: true
475
- enableExecutePlan: true
475
+ enableExecutePlan: false
476
476
  max_iterations: 40
477
477
  prompt_type: code-explorer
478
478
  allowBash: true
@@ -524,7 +524,7 @@ steps:
524
524
  - "curl:-s:*"
525
525
  - "curl:*"
526
526
  timeout: 60000
527
- completion_prompt: |
527
+ _completion_prompt: |
528
528
  Before finalizing your answer, triple-check everything:
529
529
 
530
530
  Challenge assumptions:
@@ -766,7 +766,7 @@ steps:
766
766
  # ProbeAgent resolves "*" and "!" patterns natively.
767
767
  ai_allowed_tools_js: |
768
768
  // Start with wildcard — allow all tools by default
769
- const excluded = ['search', 'query', 'extract', 'listFiles', 'searchFiles', 'delegate'];
769
+ const excluded = ['search', 'query', 'extract', 'listFiles', 'searchFiles', 'delegate', 'analyze_all'];
770
770
  const bashEnabled = outputs['build-config']?.bash_enabled === true;
771
771
  if (!bashEnabled) {
772
772
  excluded.push('bash');
@@ -472,7 +472,7 @@ steps:
472
472
  ai:
473
473
  skip_code_context: true
474
474
  enableDelegate: true
475
- enableExecutePlan: true
475
+ enableExecutePlan: false
476
476
  max_iterations: 40
477
477
  prompt_type: code-explorer
478
478
  allowBash: true
@@ -524,7 +524,7 @@ steps:
524
524
  - "curl:-s:*"
525
525
  - "curl:*"
526
526
  timeout: 60000
527
- completion_prompt: |
527
+ _completion_prompt: |
528
528
  Before finalizing your answer, triple-check everything:
529
529
 
530
530
  Challenge assumptions:
@@ -0,0 +1,672 @@
1
+ # A2A Provider (Agent-to-Agent Protocol)
2
+
3
+ Visor implements the [A2A (Agent-to-Agent) protocol](https://github.com/google/A2A) for agent interoperability. This enables two modes of operation:
4
+
5
+ - **Server mode** — Visor exposes workflows as a discoverable A2A agent that external systems can call
6
+ - **Client mode** — Visor calls external A2A agents as workflow steps using `type: a2a`
7
+
8
+ ### A2A vs MCP
9
+
10
+ | | A2A | MCP |
11
+ |---|---|---|
12
+ | **Pattern** | Agent-to-Agent task delegation | Agent-to-Tool function calls |
13
+ | **Communication** | Stateful tasks with lifecycle | Stateless function invocation |
14
+ | **Input** | Natural language + structured data | Typed JSON Schema parameters |
15
+ | **Discovery** | Agent Card at `/.well-known/agent-card.json` | Tool listing via `tools/list` |
16
+ | **Multi-turn** | Built-in (input_required state) | Not applicable |
17
+
18
+ Use MCP when you need deterministic tool calls with typed schemas. Use A2A when you need to delegate complex tasks to another agent that may require multiple turns or long-running execution.
19
+
20
+ ---
21
+
22
+ ## Quick Start
23
+
24
+ ### Server: Expose a Workflow as an A2A Agent
25
+
26
+ ```yaml
27
+ # .visor.yaml
28
+ version: "1.0"
29
+
30
+ agent_protocol:
31
+ enabled: true
32
+ protocol: a2a
33
+ port: 9000
34
+ agent_card_inline:
35
+ name: "Review Agent"
36
+ description: "AI code review"
37
+ skills:
38
+ - id: review
39
+ name: Code Review
40
+ description: Review code for issues
41
+ default_workflow: review
42
+
43
+ steps:
44
+ review:
45
+ type: ai
46
+ prompt: "Review the submitted code for issues"
47
+ on: [manual]
48
+ ```
49
+
50
+ ```bash
51
+ # Start the A2A server
52
+ visor --a2a --config .visor.yaml
53
+
54
+ # Test with curl
55
+ curl http://localhost:9000/.well-known/agent-card.json
56
+ curl -X POST http://localhost:9000/message:send \
57
+ -H "Content-Type: application/json" \
58
+ -d '{"message": {"message_id": "1", "role": "user", "parts": [{"text": "Review my code"}]}}'
59
+ ```
60
+
61
+ ### Client: Call an External A2A Agent
62
+
63
+ ```yaml
64
+ steps:
65
+ scan:
66
+ type: a2a
67
+ agent_url: "http://compliance-agent:9000"
68
+ message: "Review PR #{{ pr.number }}: {{ pr.title }}"
69
+ blocking: true
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Server Mode: Visor as an A2A Agent
75
+
76
+ ### Enabling the Server
77
+
78
+ Start with the `--a2a` CLI flag:
79
+
80
+ ```bash
81
+ visor --a2a --config .visor.yaml
82
+ ```
83
+
84
+ Or enable in configuration:
85
+
86
+ ```yaml
87
+ agent_protocol:
88
+ enabled: true
89
+ protocol: a2a
90
+ port: 9000 # default: 9000
91
+ host: "0.0.0.0" # default: 0.0.0.0
92
+ ```
93
+
94
+ A2A can run alongside other modes:
95
+
96
+ ```bash
97
+ visor --a2a --slack --config .visor.yaml # A2A + Slack simultaneously
98
+ ```
99
+
100
+ ### Agent Card
101
+
102
+ The Agent Card describes your agent to external clients. Define it inline or load from a file:
103
+
104
+ ```yaml
105
+ # Inline
106
+ agent_protocol:
107
+ agent_card_inline:
108
+ name: "Code Review Agent"
109
+ description: "AI-powered code review"
110
+ version: "1.0.0"
111
+ provider:
112
+ organization: "My Org"
113
+ url: "https://myorg.com"
114
+ skills:
115
+ - id: security
116
+ name: Security Review
117
+ description: OWASP Top 10 analysis
118
+ tags: [security, owasp]
119
+ - id: performance
120
+ name: Performance Review
121
+ description: Performance bottleneck detection
122
+ tags: [performance]
123
+ supported_interfaces:
124
+ - url: "http://localhost:9000"
125
+ protocol_binding: "a2a/v1"
126
+ capabilities:
127
+ streaming: false
128
+ push_notifications: false
129
+
130
+ # Or load from file
131
+ agent_protocol:
132
+ agent_card: "./agent-card.json"
133
+ ```
134
+
135
+ The Agent Card is served publicly at `GET /.well-known/agent-card.json` (no authentication required).
136
+
137
+ ### Skill Routing
138
+
139
+ Map incoming A2A skill IDs to internal Visor workflows:
140
+
141
+ ```yaml
142
+ agent_protocol:
143
+ skill_routing:
144
+ security: security-review # A2A skill "security" → workflow "security-review"
145
+ performance: performance-review
146
+ default_workflow: general-review # Fallback when skill not matched
147
+ ```
148
+
149
+ When a client sends a message with `metadata.skill_id: "security"`, Visor routes it to the `security-review` workflow. Unmatched skills use `default_workflow`.
150
+
151
+ ### Authentication
152
+
153
+ Configure authentication for inbound requests:
154
+
155
+ ```yaml
156
+ agent_protocol:
157
+ auth:
158
+ type: bearer # bearer | api_key | none
159
+ token_env: AGENT_AUTH_TOKEN # Environment variable containing the token
160
+ ```
161
+
162
+ **Bearer token:**
163
+ ```yaml
164
+ auth:
165
+ type: bearer
166
+ token_env: AGENT_AUTH_TOKEN # Checked via Authorization: Bearer <token>
167
+ ```
168
+
169
+ **API key:**
170
+ ```yaml
171
+ auth:
172
+ type: api_key
173
+ key_env: AGENT_API_KEY
174
+ header_name: X-API-Key # default: x-api-key
175
+ param_name: api_key # also checked as query parameter
176
+ ```
177
+
178
+ > The Agent Card endpoint (`/.well-known/agent-card.json`) is always public regardless of auth configuration.
179
+
180
+ ### HTTP Endpoints
181
+
182
+ | Method | Path | Auth | Description |
183
+ |--------|------|------|-------------|
184
+ | `GET` | `/.well-known/agent-card.json` | No | Agent Card for discovery |
185
+ | `POST` | `/message:send` | Yes | Submit a task / send a message |
186
+ | `GET` | `/tasks/{id}` | Yes | Get task by ID |
187
+ | `GET` | `/tasks` | Yes | List all tasks |
188
+ | `POST` | `/tasks/{id}:cancel` | Yes | Cancel a running task |
189
+
190
+ ### Task Lifecycle
191
+
192
+ Tasks follow a state machine with these transitions:
193
+
194
+ ```
195
+ ┌─────────────┐
196
+ │ submitted │
197
+ └──────┬──────┘
198
+ ┌────────────┼────────────┐
199
+ v v v
200
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
201
+ │ working │ │ canceled │ │ rejected │
202
+ └────┬─────┘ └──────────┘ └──────────┘
203
+ ┌─────┬───┼───┬─────────┐
204
+ v v v v v
205
+ ┌─────────┐ │ ┌───┐ │ ┌────────────────┐
206
+ │completed│ │ │ │ │ │input_required │──→ working (resumed)
207
+ └─────────┘ │ │ │ │ └────────────────┘
208
+ ┌─────┘ │ │ └──────────┐
209
+ v v v v
210
+ ┌──────────┐ ┌──────────┐ ┌────────────────┐
211
+ │ failed │ │ canceled │ │ auth_required │──→ working (resumed)
212
+ └──────────┘ └──────────┘ └────────────────┘
213
+ ```
214
+
215
+ **Terminal states:** `completed`, `failed`, `canceled`, `rejected`
216
+
217
+ | State | Description |
218
+ |-------|-------------|
219
+ | `submitted` | Task created, waiting to be picked up |
220
+ | `working` | Workflow engine is processing the task |
221
+ | `input_required` | Agent needs additional input from the client |
222
+ | `auth_required` | Agent needs authentication credentials |
223
+ | `completed` | Task finished successfully |
224
+ | `failed` | Task execution encountered an error |
225
+ | `canceled` | Task was canceled by the client |
226
+ | `rejected` | Task was rejected at submission |
227
+
228
+ ### Task Queue
229
+
230
+ For async execution, configure the task queue:
231
+
232
+ ```yaml
233
+ agent_protocol:
234
+ queue:
235
+ poll_interval: 1000 # Poll database every N ms (default: 1000)
236
+ max_concurrent: 5 # Max concurrent tasks (default: 5)
237
+ stale_claim_timeout: 300000 # Worker timeout in ms (default: 300000)
238
+ task_ttl: "7d" # Task retention period (default: 7d)
239
+ ```
240
+
241
+ **Blocking vs async:**
242
+ - **Blocking** (default): The `POST /message:send` request waits for the workflow to complete and returns the full task with artifacts.
243
+ - **Async**: Set `configuration.blocking: false` in the request. Returns the task ID immediately; the client polls `GET /tasks/{id}` for status updates.
244
+
245
+ ### TLS
246
+
247
+ For production deployments:
248
+
249
+ ```yaml
250
+ agent_protocol:
251
+ tls:
252
+ cert: "/path/to/cert.pem"
253
+ key: "/path/to/key.pem"
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Client Mode: Calling External A2A Agents
259
+
260
+ Use `type: a2a` to call external A2A-compatible agents from your workflow.
261
+
262
+ ### Basic Usage
263
+
264
+ ```yaml
265
+ steps:
266
+ compliance-scan:
267
+ type: a2a
268
+ agent_url: "http://compliance-agent:9000"
269
+ message: |
270
+ Review PR #{{ pr.number }}: {{ pr.title }}
271
+ Files changed: {{ files | size }}
272
+ blocking: true
273
+ timeout: 60000
274
+ ```
275
+
276
+ ### Agent Discovery
277
+
278
+ Specify the agent endpoint in one of two ways (mutually exclusive):
279
+
280
+ ```yaml
281
+ # Option 1: Direct URL to the agent
282
+ agent_url: "http://agent.example.com:9000"
283
+
284
+ # Option 2: URL to the Agent Card (endpoint resolved from card)
285
+ agent_card: "https://agent.example.com/.well-known/agent-card.json"
286
+ ```
287
+
288
+ When using `agent_card`, Visor fetches the card, caches it for 5 minutes, and resolves the endpoint from `supported_interfaces`.
289
+
290
+ ### Authentication
291
+
292
+ ```yaml
293
+ steps:
294
+ scan:
295
+ type: a2a
296
+ agent_url: "http://agent:9000"
297
+ message: "Review this code"
298
+ auth:
299
+ scheme: bearer # bearer | api_key
300
+ token_env: AGENT_TOKEN # Environment variable with the token
301
+ # header_name: X-API-Key # For api_key scheme (default: x-api-key)
302
+ ```
303
+
304
+ ### Message Construction
305
+
306
+ **Text message** (Liquid template):
307
+ ```yaml
308
+ message: |
309
+ Review PR #{{ pr.number }}: {{ pr.title }}
310
+ Author: {{ pr.author }}
311
+ ```
312
+
313
+ **Structured data** (Liquid-templated key-value pairs sent as data parts):
314
+ ```yaml
315
+ data:
316
+ repo_context: '{{ pr.repo | json }}'
317
+ file_list: '{{ files | json }}'
318
+ ```
319
+
320
+ **File attachments:**
321
+ ```yaml
322
+ files:
323
+ - url: "https://example.com/requirements.txt"
324
+ media_type: "text/plain"
325
+ filename: "requirements.txt"
326
+ ```
327
+
328
+ ### Polling and Multi-Turn
329
+
330
+ ```yaml
331
+ steps:
332
+ interactive-agent:
333
+ type: a2a
334
+ agent_url: "http://agent:9000"
335
+ message: "Analyze {{ pr.title }}"
336
+
337
+ blocking: true # Wait for completion (default: true)
338
+ timeout: 300000 # Max wait in ms (default: 300000)
339
+ poll_interval: 2000 # Poll frequency in ms (default: 2000)
340
+
341
+ # Multi-turn conversation
342
+ max_turns: 3 # Max conversation turns (default: 1)
343
+ on_input_required: | # Auto-reply when agent asks for more info
344
+ Here is additional context:
345
+ {{ pr.body }}
346
+ ```
347
+
348
+ When the agent enters `input_required` state, Visor automatically sends the `on_input_required` template as a follow-up message. This continues up to `max_turns`.
349
+
350
+ ### Output Transformation
351
+
352
+ Transform agent responses into structured issues with JavaScript:
353
+
354
+ ```yaml
355
+ steps:
356
+ scan:
357
+ type: a2a
358
+ agent_url: "http://agent:9000"
359
+ message: "Security scan"
360
+ transform_js: |
361
+ return {
362
+ issues: (output.issues || []).map(function(i) {
363
+ return {
364
+ file: i.file,
365
+ line: i.line || 0,
366
+ ruleId: 'a2a/' + (i.ruleId || 'issue'),
367
+ message: i.message,
368
+ severity: i.severity || 'warning'
369
+ };
370
+ })
371
+ };
372
+ ```
373
+
374
+ ### Error Handling
375
+
376
+ A2A errors are surfaced as issues with `ruleId: a2a/error`:
377
+
378
+ | Error | When |
379
+ |-------|------|
380
+ | `A2ATimeoutError` | Task didn't complete within `timeout` |
381
+ | `A2AMaxTurnsExceededError` | Conversation exceeded `max_turns` |
382
+ | `A2AInputRequiredError` | Agent needs input but `max_turns` exhausted |
383
+ | `A2AAuthRequiredError` | Agent requires authentication credentials |
384
+ | `A2ATaskFailedError` | Task execution failed on the remote agent |
385
+ | `A2ATaskRejectedError` | Task was rejected or canceled |
386
+ | `A2ARequestError` | HTTP request to the agent failed |
387
+ | `AgentCardFetchError` | Failed to fetch Agent Card |
388
+ | `InvalidAgentCardError` | Agent Card is malformed |
389
+
390
+ ---
391
+
392
+ ## Task Management CLI
393
+
394
+ Monitor and manage A2A tasks with `visor tasks`:
395
+
396
+ ```bash
397
+ visor tasks # List all tasks (alias for list)
398
+ visor tasks list # List tasks
399
+ visor tasks list --state working # Filter by state
400
+ visor tasks list --agent security-review # Filter by workflow
401
+ visor tasks list --limit 50 # Show more results
402
+ visor tasks list --output json # JSON output
403
+ visor tasks list --watch # Live refresh every 2s
404
+ visor tasks stats # Queue summary statistics
405
+ visor tasks stats --output json # Stats as JSON
406
+ visor tasks cancel <task-id> # Cancel a running task
407
+ visor tasks help # Show usage
408
+ ```
409
+
410
+ **Flags:**
411
+
412
+ | Flag | Description | Default |
413
+ |------|-------------|---------|
414
+ | `--state <state>` | Filter by task state | all |
415
+ | `--agent <workflow-id>` | Filter by workflow | all |
416
+ | `--limit <n>` | Number of tasks to show | 20 |
417
+ | `--output <format>` | Output format: `table`, `json`, `markdown` | table |
418
+ | `--watch` | Refresh every 2 seconds | off |
419
+
420
+ ---
421
+
422
+ ## Configuration Reference
423
+
424
+ ### Server-Side: `agent_protocol`
425
+
426
+ | Key | Type | Default | Description |
427
+ |-----|------|---------|-------------|
428
+ | `enabled` | boolean | `false` | Enable the A2A server |
429
+ | `protocol` | string | `"a2a"` | Protocol binding |
430
+ | `port` | number | `9000` | HTTP listen port |
431
+ | `host` | string | `"0.0.0.0"` | HTTP bind address |
432
+ | `public_url` | string | auto | Public URL for Agent Card |
433
+ | `agent_card_inline` | object | - | Inline Agent Card definition |
434
+ | `agent_card` | string | - | Path to Agent Card JSON file |
435
+ | `auth` | object | - | Authentication config |
436
+ | `auth.type` | string | - | `bearer`, `api_key`, or `none` |
437
+ | `auth.token_env` | string | - | Env var for bearer token |
438
+ | `auth.key_env` | string | - | Env var for API key |
439
+ | `auth.header_name` | string | `"x-api-key"` | Custom header for API key |
440
+ | `auth.param_name` | string | `"api_key"` | Query parameter for API key |
441
+ | `skill_routing` | object | - | Map of skill_id to workflow name |
442
+ | `default_workflow` | string | - | Fallback workflow for unmatched skills |
443
+ | `task_ttl` | string | `"7d"` | Task retention period |
444
+ | `queue.poll_interval` | number | `1000` | Queue poll interval in ms |
445
+ | `queue.max_concurrent` | number | `5` | Max concurrent task executions |
446
+ | `queue.stale_claim_timeout` | number | `300000` | Worker stale claim timeout in ms |
447
+ | `tls.cert` | string | - | Path to TLS certificate |
448
+ | `tls.key` | string | - | Path to TLS private key |
449
+
450
+ ### Client-Side: `type: a2a` Check Provider
451
+
452
+ | Key | Type | Default | Required | Description |
453
+ |-----|------|---------|----------|-------------|
454
+ | `agent_url` | string | - | one of | Direct agent endpoint URL |
455
+ | `agent_card` | string | - | one of | URL to Agent Card |
456
+ | `message` | string | - | yes | Liquid template for the message text |
457
+ | `data` | object | - | no | Liquid-templated structured data parts |
458
+ | `files` | array | - | no | File attachments (`url`, `media_type`, `filename`) |
459
+ | `auth.scheme` | string | - | no | `bearer` or `api_key` |
460
+ | `auth.token_env` | string | - | no | Env var containing auth token |
461
+ | `auth.header_name` | string | `"x-api-key"` | no | Custom header for API key |
462
+ | `blocking` | boolean | `true` | no | Wait for task completion |
463
+ | `timeout` | number | `300000` | no | Max wait time in ms |
464
+ | `poll_interval` | number | `2000` | no | Poll interval in ms |
465
+ | `max_turns` | number | `1` | no | Max conversation turns |
466
+ | `on_input_required` | string | - | no | Liquid template for auto-reply |
467
+ | `transform_js` | string | - | no | JavaScript output transformation |
468
+ | `accepted_output_modes` | string[] | `["text/plain", "application/json"]` | no | Accepted MIME types |
469
+
470
+ ---
471
+
472
+ ## Examples
473
+
474
+ ### Server: Code Review Agent
475
+
476
+ Full example from [examples/a2a-agent-example.yaml](../examples/a2a-agent-example.yaml):
477
+
478
+ ```yaml
479
+ version: "1.0"
480
+
481
+ agent_protocol:
482
+ enabled: true
483
+ protocol: a2a
484
+ port: 9000
485
+ host: "0.0.0.0"
486
+
487
+ agent_card_inline:
488
+ name: "Code Review Agent"
489
+ description: "AI-powered code review agent built with Visor"
490
+ version: "1.0.0"
491
+ provider:
492
+ organization: "Visor"
493
+ skills:
494
+ - id: security
495
+ name: Security Review
496
+ description: Analyze code for security vulnerabilities (OWASP Top 10)
497
+ tags: [security, owasp]
498
+ - id: performance
499
+ name: Performance Review
500
+ description: Analyze code for performance issues and bottlenecks
501
+ tags: [performance]
502
+ supported_interfaces:
503
+ - url: "http://localhost:9000"
504
+ protocol_binding: "a2a/v1"
505
+ capabilities:
506
+ streaming: false
507
+ push_notifications: false
508
+
509
+ auth:
510
+ type: bearer
511
+ token_env: AGENT_AUTH_TOKEN
512
+
513
+ skill_routing:
514
+ security: security-review
515
+ performance: performance-review
516
+ default_workflow: general-review
517
+
518
+ task_ttl: "7d"
519
+ queue:
520
+ max_concurrent: 5
521
+
522
+ steps:
523
+ security-review:
524
+ type: ai
525
+ prompt: |
526
+ Perform a security review focusing on OWASP Top 10 vulnerabilities.
527
+ Check for SQL injection, XSS, CSRF, and authentication issues.
528
+ on: [manual]
529
+
530
+ performance-review:
531
+ type: ai
532
+ prompt: |
533
+ Review for performance issues: N+1 queries, memory leaks,
534
+ unnecessary allocations, and algorithmic complexity.
535
+ on: [manual]
536
+
537
+ general-review:
538
+ type: ai
539
+ prompt: |
540
+ General code quality review: naming, structure, error handling,
541
+ and adherence to project conventions.
542
+ on: [manual]
543
+ ```
544
+
545
+ ```bash
546
+ # Start
547
+ visor --a2a --config examples/a2a-agent-example.yaml
548
+
549
+ # Discover
550
+ curl http://localhost:9000/.well-known/agent-card.json | jq .
551
+
552
+ # Send a task targeting the security skill
553
+ curl -X POST http://localhost:9000/message:send \
554
+ -H "Content-Type: application/json" \
555
+ -H "Authorization: Bearer $AGENT_AUTH_TOKEN" \
556
+ -d '{
557
+ "message": {
558
+ "message_id": "msg-1",
559
+ "role": "user",
560
+ "parts": [{"text": "Review auth.py for security issues"}],
561
+ "metadata": {"skill_id": "security"}
562
+ }
563
+ }'
564
+
565
+ # Monitor tasks
566
+ visor tasks list --watch
567
+ ```
568
+
569
+ ### Client: Multi-Agent Composition
570
+
571
+ Chain multiple A2A agents and aggregate results:
572
+
573
+ ```yaml
574
+ steps:
575
+ compliance-scan:
576
+ type: a2a
577
+ agent_url: "http://compliance-agent:9000"
578
+ message: "Check compliance for PR #{{ pr.number }}"
579
+ blocking: true
580
+
581
+ security-scan:
582
+ type: a2a
583
+ agent_url: "http://security-agent:9000"
584
+ message: "Security review for PR #{{ pr.number }}"
585
+ blocking: true
586
+
587
+ summarize:
588
+ type: ai
589
+ depends_on: [compliance-scan, security-scan]
590
+ prompt: |
591
+ Summarize findings from two agents:
592
+ Compliance: {{ outputs["compliance-scan"] | json }}
593
+ Security: {{ outputs["security-scan"] | json }}
594
+ ```
595
+
596
+ ### Multi-Turn Conversation
597
+
598
+ Handle agents that ask follow-up questions:
599
+
600
+ ```yaml
601
+ steps:
602
+ interactive-review:
603
+ type: a2a
604
+ agent_card: "https://agent.example.com/.well-known/agent-card.json"
605
+ message: "Analyze {{ pr.title }} for best practices"
606
+ max_turns: 3
607
+ on_input_required: |
608
+ Here is additional context:
609
+ {{ pr.body }}
610
+ transform_js: |
611
+ return {
612
+ issues: (output.issues || []).map(function(i) {
613
+ return {
614
+ file: i.file,
615
+ line: i.line || 0,
616
+ ruleId: 'a2a/' + (i.ruleId || 'issue'),
617
+ message: i.message,
618
+ severity: i.severity || 'warning'
619
+ };
620
+ })
621
+ };
622
+ ```
623
+
624
+ ---
625
+
626
+ ## Security Considerations
627
+
628
+ - **Always configure auth for production** — without it, anyone can submit tasks to your agent
629
+ - **Use `token_env` / `key_env`** — never hardcode tokens in config files
630
+ - **Enable TLS** for public-facing servers
631
+ - **Agent Card is public** — it's served without auth, so don't include sensitive information
632
+ - **Task TTL** — set appropriate retention to limit stored data (`task_ttl: "7d"`)
633
+ - **Token comparison** uses timing-safe comparison to prevent timing attacks
634
+
635
+ ---
636
+
637
+ ## Debugging
638
+
639
+ ```bash
640
+ # Start with debug logging
641
+ visor --a2a --debug --config .visor.yaml
642
+
643
+ # Verify Agent Card is served correctly
644
+ curl http://localhost:9000/.well-known/agent-card.json | jq .
645
+
646
+ # Monitor live task queue
647
+ visor tasks list --watch
648
+
649
+ # Check queue statistics
650
+ visor tasks stats
651
+
652
+ # View specific task
653
+ visor tasks list --state failed # Find failed tasks
654
+ ```
655
+
656
+ With OpenTelemetry enabled, A2A tasks emit spans with:
657
+ - `agent.task.id` — Task ID
658
+ - `agent.task.state` — Current state
659
+ - `agent.task.workflow_id` — Target workflow
660
+
661
+ ---
662
+
663
+ ## Related Documentation
664
+
665
+ - [MCP Provider](./mcp-provider.md) — MCP tool integration (complementary to A2A)
666
+ - [HTTP Integration](./http.md) — HTTP server and webhooks
667
+ - [Workflows](./workflows.md) — Reusable workflow definitions
668
+ - [Configuration](./configuration.md) — Configuration reference
669
+ - [Architecture](./architecture.md) — System architecture overview
670
+ - [Security](./security.md) — Security best practices
671
+ - [Debugging](./debugging.md) — Debugging techniques
672
+ - [RFC: A2A Protocol Support](../rfc/001-a2a-protocol-support.md) — Design document
@@ -27,7 +27,7 @@ This document provides a comprehensive overview of Visor's internal architecture
27
27
 
28
28
  ## System Overview
29
29
 
30
- Visor is an AI-powered workflow orchestration tool that can run as a GitHub Action, CLI tool, or Slack bot. The system uses a state machine-based execution engine to orchestrate checks (steps) with sophisticated dependency resolution, routing, and error handling.
30
+ Visor is an AI-powered workflow orchestration tool that can run as a GitHub Action, CLI tool, Slack bot, or A2A agent server. The system uses a state machine-based execution engine to orchestrate checks (steps) with sophisticated dependency resolution, routing, and error handling.
31
31
 
32
32
  ### High-Level Architecture Diagram
33
33
 
@@ -36,16 +36,16 @@ Visor is an AI-powered workflow orchestration tool that can run as a GitHub Acti
36
36
  | Entry Points |
37
37
  +------------------+
38
38
  | |
39
- +-------------+---+----------+---+-------------+
40
- | | | |
41
- v v v v
42
- +------+------+ +------+------+ +---+---+ +-----+-----+
43
- | GitHub | | CLI | | Slack | | HTTP |
44
- | Action | | (cli-main) | | Socket| | Webhook |
45
- | (index.ts) | | | | Mode | | Server |
46
- +------+------+ +------+------+ +---+---+ +-----+-----+
47
- | | | |
48
- +--------+--------+--------------+-------------+
39
+ +------+------+-----+----+--------+---+----------+
40
+ | | | | |
41
+ v v v v v
42
+ +------+------+ +---+----+ +---+---+ +--+-------+ +----+------+
43
+ | GitHub | | CLI | | Slack | | HTTP | | A2A |
44
+ | Action | | | | Socket| | Webhook | | Agent |
45
+ | (index.ts) | | | | Mode | | Server | | Server |
46
+ +------+------+ +---+----+ +---+---+ +--+-------+ +----+------+
47
+ | | | | |
48
+ +------+------+----------+--------+--------------+
49
49
  |
50
50
  v
51
51
  +----------+-----------+
@@ -82,7 +82,7 @@ Visor is an AI-powered workflow orchestration tool that can run as a GitHub Acti
82
82
 
83
83
  | Component | Description |
84
84
  |-----------|-------------|
85
- | **Entry Points** | GitHub Action, CLI, Slack Socket Mode, HTTP webhooks |
85
+ | **Entry Points** | GitHub Action, CLI, Slack Socket Mode, HTTP webhooks, A2A Agent Protocol |
86
86
  | **Configuration Manager** | Loads and validates YAML configuration |
87
87
  | **State Machine Engine** | Orchestrates check execution with wave-based scheduling |
88
88
  | **Provider Registry** | Registry of pluggable check providers |
@@ -164,6 +164,33 @@ http_server:
164
164
  transform: "{{ request.body | json }}"
165
165
  ```
166
166
 
167
+ ### A2A Agent Server (`src/agent-protocol/a2a-frontend.ts`)
168
+
169
+ The A2A (Agent-to-Agent) entry point exposes Visor workflows as standards-compliant A2A agents:
170
+
171
+ ```bash
172
+ visor --a2a --config .visor.yaml
173
+ ```
174
+
175
+ **Responsibilities:**
176
+ - Serve Agent Card at `/.well-known/agent-card.json` for discovery
177
+ - Accept tasks via `POST /message:send`
178
+ - Route incoming A2A skills to internal workflows via `skill_routing`
179
+ - Manage task lifecycle (submitted → working → completed/failed)
180
+ - Persist tasks in SQLite via `TaskStore`
181
+ - Execute workflows through the state machine engine
182
+
183
+ **Supported A2A Endpoints:**
184
+ | Method | Path | Auth | Description |
185
+ |--------|------|------|-------------|
186
+ | `GET` | `/.well-known/agent-card.json` | No | Agent Card for discovery |
187
+ | `POST` | `/message:send` | Yes | Submit a task |
188
+ | `GET` | `/tasks/{id}` | Yes | Get task status |
189
+ | `GET` | `/tasks` | Yes | List tasks |
190
+ | `POST` | `/tasks/{id}:cancel` | Yes | Cancel a task |
191
+
192
+ See [A2A Provider](./a2a-provider.md) for complete documentation.
193
+
167
194
  ---
168
195
 
169
196
  ## Core Components
@@ -264,6 +291,104 @@ checks:
264
291
  run: [aggregation-step]
265
292
  ```
266
293
 
294
+ ### Agent Protocol Layer
295
+
296
+ The A2A feature introduces a task-based execution layer that sits between external clients and the workflow engine. This is architecturally separate from the step-level state machine — it governs the lifecycle of inbound agent tasks.
297
+
298
+ ```
299
+ External A2A Client
300
+
301
+
302
+ ┌─────────────────────┐
303
+ │ A2A Frontend │ HTTP server, auth, Agent Card
304
+ │ (a2a-frontend.ts) │
305
+ └──────────┬──────────┘
306
+
307
+
308
+ ┌─────────────────────┐ ┌─────────────────────┐
309
+ │ Task Store │◄───►│ Task Queue │
310
+ │ (SQLite) │ │ (async execution) │
311
+ └──────────┬──────────┘ └──────────┬──────────┘
312
+ │ │
313
+ ▼ ▼
314
+ ┌──────────────────────────────────────────────────┐
315
+ │ State Machine Execution Engine │
316
+ │ (same engine used by CLI, GitHub Action, etc.) │
317
+ └──────────────────────────────────────────────────┘
318
+
319
+
320
+ ┌──────────────────────────────────────────────────┐
321
+ │ Provider Registry → [ai, a2a, command, ...] │
322
+ └──────────────────────────────────────────────────┘
323
+ ```
324
+
325
+ #### Task Store (`src/agent-protocol/task-store.ts`)
326
+
327
+ SQLite-backed persistence for A2A tasks:
328
+
329
+ ```sql
330
+ CREATE TABLE agent_tasks (
331
+ id TEXT PRIMARY KEY, -- UUID
332
+ context_id TEXT NOT NULL, -- Session grouping
333
+ state TEXT NOT NULL, -- Task state
334
+ created_at TEXT NOT NULL, -- ISO 8601
335
+ updated_at TEXT NOT NULL,
336
+ request_message TEXT NOT NULL, -- JSON: original message
337
+ artifacts TEXT DEFAULT '[]', -- JSON: AgentArtifact[]
338
+ history TEXT DEFAULT '[]', -- JSON: AgentMessage[]
339
+ workflow_id TEXT, -- Target workflow
340
+ run_id TEXT, -- Engine run correlation
341
+ claimed_by TEXT, -- Worker ID (queue)
342
+ claimed_at TEXT, -- Claim timestamp
343
+ ttl TEXT -- Expiration
344
+ );
345
+ ```
346
+
347
+ The store provides CRUD operations with state transition enforcement — invalid transitions (e.g., `completed` → `working`) throw `InvalidStateTransitionError`.
348
+
349
+ #### Task Queue (`src/agent-protocol/task-queue.ts`)
350
+
351
+ Manages async task execution with configurable concurrency:
352
+
353
+ - Polls the database at `poll_interval` for unclaimed `submitted` tasks
354
+ - Claims tasks using a worker ID with `stale_claim_timeout` to recover from crashed workers
355
+ - Feeds tasks to the state machine engine, limited by `max_concurrent`
356
+ - Updates task state and artifacts on completion
357
+
358
+ #### Task State Machine (`src/agent-protocol/state-transitions.ts`)
359
+
360
+ Separate from the workflow engine state machine — this governs task lifecycle:
361
+
362
+ ```
363
+ submitted ──→ working ──→ completed (terminal)
364
+ │ ├──→ failed (terminal)
365
+ │ ├──→ canceled (terminal)
366
+ │ ├──→ input_required ──→ working (resumed)
367
+ │ └──→ auth_required ──→ working (resumed)
368
+ ├──→ canceled (terminal)
369
+ └──→ rejected (terminal)
370
+ ```
371
+
372
+ Terminal states: `completed`, `failed`, `canceled`, `rejected`.
373
+
374
+ #### Agent Card & Discovery
375
+
376
+ The Agent Card is a JSON document describing the agent's capabilities:
377
+
378
+ ```typescript
379
+ interface AgentCard {
380
+ name: string;
381
+ description?: string;
382
+ version?: string;
383
+ provider?: { organization: string; url?: string };
384
+ skills?: AgentSkill[]; // Advertised capabilities
385
+ supported_interfaces?: Array<{ url: string; protocol_binding?: string }>;
386
+ capabilities?: { streaming?: boolean; push_notifications?: boolean };
387
+ }
388
+ ```
389
+
390
+ Skills are mapped to internal workflows via `skill_routing` configuration. When a client sends a message with `metadata.skill_id`, the frontend resolves the target workflow and dispatches execution.
391
+
267
392
  ---
268
393
 
269
394
  ## Provider Architecture
@@ -311,6 +436,7 @@ class CheckProviderRegistry {
311
436
 
312
437
  | Provider | Type | Description |
313
438
  |----------|------|-------------|
439
+ | `a2a` | A2A Agent | Calls external A2A-compatible agents |
314
440
  | `ai` | AI-powered | Uses Gemini, Claude, OpenAI, or Bedrock for analysis |
315
441
  | `command` | Command | Executes shell commands |
316
442
  | `script` | Script | Executes JavaScript in a sandbox |
@@ -508,6 +634,19 @@ checks:
508
634
  {{ data.message }}
509
635
  ```
510
636
 
637
+ ### A2A Protocol
638
+
639
+ External agents and orchestrators send tasks via the A2A protocol:
640
+
641
+ 1. Client fetches Agent Card from `GET /.well-known/agent-card.json`
642
+ 2. Client sends `POST /message:send` with `skill_id` in metadata
643
+ 3. A2A Frontend authenticates the request (bearer/api_key)
644
+ 4. Task created in TaskStore (state: `submitted`)
645
+ 5. Skill routing maps `skill_id` → internal workflow name
646
+ 6. Engine executes the workflow (same engine as CLI/GitHub Action)
647
+ 7. Task updated with artifacts (state: `completed`)
648
+ 8. Client receives response (blocking) or polls `GET /tasks/{id}` (async)
649
+
511
650
  ---
512
651
 
513
652
  ## Data Flow
@@ -1063,6 +1202,7 @@ Currently, Visor does not cache AI responses between runs. For expensive operati
1063
1202
  - [Security](./security.md) - Security overview and best practices
1064
1203
  - [Providers](./providers/) - Provider-specific documentation
1065
1204
  - [Custom Tools](./custom-tools.md) - Creating custom tools
1205
+ - [A2A Provider](./a2a-provider.md) - Agent-to-Agent protocol integration
1066
1206
  - [MCP Provider](./mcp-provider.md) - MCP integration details
1067
1207
  - [Command Provider](./command-provider.md) - Shell command execution
1068
1208
  - [HTTP Integration](./http.md) - HTTP server and client features
@@ -1100,6 +1240,7 @@ src/
1100
1240
  providers/
1101
1241
  check-provider.interface.ts # Provider base class
1102
1242
  check-provider-registry.ts # Provider registry
1243
+ a2a-check-provider.ts # A2A agent client provider
1103
1244
  ai-check-provider.ts # AI provider (Gemini, Claude, OpenAI)
1104
1245
  claude-code-check-provider.ts # Claude Code SDK provider
1105
1246
  command-check-provider.ts # Shell command provider
@@ -1122,6 +1263,17 @@ src/
1122
1263
  event-bus.ts # Event bus for frontends
1123
1264
  types.ts # Event envelope types
1124
1265
 
1266
+ agent-protocol/
1267
+ a2a-frontend.ts # A2A HTTP server and endpoints
1268
+ types.ts # Protocol-agnostic types and error classes
1269
+ state-transitions.ts # Task state machine validation
1270
+ task-store.ts # SQLite-backed task persistence
1271
+ task-queue.ts # Async task execution queue
1272
+ task-stream-manager.ts # SSE streaming support
1273
+ push-notification-manager.ts # Push notification delivery
1274
+ tasks-cli-handler.ts # CLI: visor tasks
1275
+ index.ts # Re-exports
1276
+
1125
1277
  frontends/
1126
1278
  host.ts # Frontend manager
1127
1279
  github/ # GitHub integration frontend
@@ -1183,6 +1335,9 @@ interface VisorConfig {
1183
1335
  // HTTP server
1184
1336
  http_server?: HttpServerConfig;
1185
1337
 
1338
+ // Agent Protocol (A2A)
1339
+ agent_protocol?: AgentProtocolConfig;
1340
+
1186
1341
  // Workflow imports
1187
1342
  imports?: string[];
1188
1343
 
@@ -1257,4 +1412,11 @@ Events that flow through the state machine:
1257
1412
  | **Scope** | Hierarchical path for nested workflow execution |
1258
1413
  | **Frontend** | Integration point (GitHub, Slack) |
1259
1414
  | **Routing** | Control flow based on check results |
1415
+ | **A2A** | Agent-to-Agent protocol — Google's open standard for agent interoperability |
1416
+ | **Agent Card** | JSON metadata describing an agent's capabilities, skills, and endpoints |
1417
+ | **Task** | A unit of work in the A2A protocol with lifecycle state (submitted → working → completed) |
1418
+ | **Skill** | A named capability advertised in an Agent Card, mapped to a Visor workflow |
1419
+ | **Skill Routing** | Configuration mapping A2A skill IDs to internal workflow names |
1420
+ | **Task Store** | SQLite-backed persistence layer for A2A tasks |
1421
+ | **Task Queue** | Async execution queue for processing A2A tasks with concurrency control |
1260
1422
  | **MCP** | Model Context Protocol - standard for AI tool integration |
@@ -113,6 +113,39 @@ visor mcp-server [options]
113
113
  - `--mcp-tool-name <name>` - Custom tool name for the MCP server
114
114
  - `--mcp-tool-description <desc>` - Custom tool description
115
115
 
116
+ #### `visor tasks`
117
+
118
+ Monitor and manage A2A agent tasks.
119
+
120
+ ```bash
121
+ visor tasks [command] [options]
122
+ ```
123
+
124
+ **Subcommands:**
125
+ - `list` (default) — List tasks with optional filters
126
+ - `stats` — Queue summary statistics
127
+ - `cancel <task-id>` — Cancel a running task
128
+ - `help` — Show usage
129
+
130
+ **Options:**
131
+ - `--state <state>` — Filter by state: `submitted`, `working`, `completed`, `failed`, `canceled`
132
+ - `--agent <workflow-id>` — Filter by workflow
133
+ - `--limit <n>` — Number of tasks to show (default: 20)
134
+ - `--output <format>` — Output format: `table` (default), `json`, `markdown`
135
+ - `--watch` — Live refresh every 2 seconds
136
+
137
+ **Examples:**
138
+ ```bash
139
+ visor tasks # List all tasks
140
+ visor tasks list --state working # Show only working tasks
141
+ visor tasks list --agent security-review # Tasks for a specific workflow
142
+ visor tasks list --output json # JSON output
143
+ visor tasks list --watch # Live monitoring
144
+ visor tasks stats # Queue summary
145
+ visor tasks stats --output json # Stats as JSON
146
+ visor tasks cancel abc123 # Cancel a task
147
+ ```
148
+
116
149
  ### Common CLI Options
117
150
 
118
151
  #### Check Selection
@@ -175,6 +208,9 @@ See [Tag Filtering](tag-filtering.md) for detailed tag filtering documentation.
175
208
 
176
209
  See [GitHub Authentication](github-auth.md) for setup guide and details.
177
210
 
211
+ #### Agent Protocol
212
+ - `--a2a` - Enable A2A Agent Protocol server mode (see [A2A Provider](a2a-provider.md))
213
+
178
214
  #### Other Options
179
215
  - `--slack` - Enable Slack Socket Mode runner
180
216
  - `--mode <mode>` - Run mode: `cli` (default) or `github-actions`
@@ -32,6 +32,7 @@ Visor supports the following check types:
32
32
 
33
33
  | Type | Description | Documentation |
34
34
  |------|-------------|---------------|
35
+ | `a2a` | Call external A2A agents | [A2A Provider](./a2a-provider.md) |
35
36
  | `ai` | AI-powered analysis using LLMs | [AI Configuration](./ai-configuration.md) |
36
37
  | `claude-code` | Claude Code SDK integration | [Claude Code](./claude-code.md) |
37
38
  | `command` | Execute shell commands | [Command Provider](./command-provider.md) |
@@ -1,6 +1,6 @@
1
1
  # Visor Documentation
2
2
 
3
- Visor is an AI-powered workflow orchestration tool for code review, automation, and CI/CD pipelines. It supports multiple AI providers, pluggable check providers, and integrates with GitHub Actions and Slack.
3
+ Visor is an AI-powered workflow orchestration tool for code review, automation, and CI/CD pipelines. It supports multiple AI providers, pluggable check providers, A2A agent interoperability, and integrates with GitHub Actions and Slack.
4
4
 
5
5
  ---
6
6
 
@@ -35,7 +35,7 @@ Visor is an AI-powered workflow orchestration tool for code review, automation,
35
35
 
36
36
  ## Providers
37
37
 
38
- Visor supports 15 provider types for different check and workflow operations.
38
+ Visor supports 16 provider types for different check and workflow operations.
39
39
 
40
40
  ### AI Providers
41
41
 
@@ -67,6 +67,12 @@ Visor supports 15 provider types for different check and workflow operations.
67
67
  | [Memory Provider](./memory.md) | Persistent key-value storage for stateful workflows |
68
68
  | [Human Input](./human-input-provider.md) | Pause workflows to collect user input via CLI, stdin, or SDK |
69
69
 
70
+ ### Agent Protocol
71
+
72
+ | Document | Description |
73
+ |----------|-------------|
74
+ | [A2A Provider](./a2a-provider.md) | Agent-to-Agent protocol: server mode, client provider, task management, and multi-agent composition |
75
+
70
76
  ### Utility Providers
71
77
 
72
78
  | Document | Description |
@@ -187,6 +193,7 @@ Internal design documents, proposals, and implementation tracking.
187
193
  | [on_init Hook](./rfc/on_init-hook.md) | Lifecycle hook for context preprocessing |
188
194
  | [Telemetry Tracing](./telemetry-tracing-rfc.md) | OpenTelemetry tracing architecture |
189
195
  | [Test Framework](./test-framework-rfc.md) | In-YAML integration test framework design |
196
+ | [A2A Protocol Support](../rfc/001-a2a-protocol-support.md) | Agent-to-Agent protocol for agent interoperability ([docs](./a2a-provider.md)) |
190
197
 
191
198
  ### Design Documents
192
199
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Visor supports multiple provider types. You can also add custom providers.
4
4
 
5
- **Built-in Providers:** ai, mcp, command, script, http, http_input, http_client, log, memory, noop, github, human-input, workflow, git-checkout, claude-code
5
+ **Built-in Providers:** a2a, ai, mcp, command, script, http, http_input, http_client, log, memory, noop, github, human-input, workflow, git-checkout, claude-code
6
6
 
7
7
  ### Custom Provider Skeleton (TypeScript)
8
8
 
@@ -18,6 +18,21 @@ class CustomCheckProvider {
18
18
 
19
19
  ### Built-in Providers
20
20
 
21
+ #### A2A Provider (`type: a2a`)
22
+ Call external A2A-compatible agents and collect their responses. Supports agent card discovery, multi-turn conversations, and JavaScript output transforms.
23
+
24
+ ```yaml
25
+ steps:
26
+ compliance-check:
27
+ type: a2a
28
+ agent_url: "http://compliance-agent:9000"
29
+ message: "Review PR #{{ pr.number }}: {{ pr.title }}"
30
+ blocking: true
31
+ timeout: 60000
32
+ ```
33
+
34
+ [Learn more](./a2a-provider.md)
35
+
21
36
  #### AI Provider (`type: ai`)
22
37
  Execute AI-powered analysis using Google Gemini, Anthropic Claude, OpenAI, or AWS Bedrock.
23
38
 
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- process.env.VISOR_VERSION = '0.1.169';
2
+ process.env.VISOR_VERSION = '0.1.170';
3
3
  process.env.PROBE_VERSION = '0.6.0-rc286';
4
- process.env.VISOR_COMMIT_SHA = '11e70cdc108f4b36afcfc1fa0c373fbcac4e9999';
5
- process.env.VISOR_COMMIT_SHORT = '11e70cd';
4
+ process.env.VISOR_COMMIT_SHA = '3e49bfdee61154013b28eba096637ac60cdd08ac';
5
+ process.env.VISOR_COMMIT_SHORT = '3e49bfd';
6
6
  /******/ (() => { // webpackBootstrap
7
7
  /******/ var __webpack_modules__ = ({
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/visor",
3
- "version": "0.1.169-ee",
3
+ "version": "0.1.170-ee",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "visor": "./dist/index.js"