# Server Connection and A2A Protocol Integration

## Overview

CleverAgents ships with a **server connection subsystem** and an **Agent-to-Agent
(A2A) protocol facade** that together form the foundation for distributed,
multi-agent deployments. This example walks through the complete workflow:
configuring a server endpoint, inspecting connection status, understanding the
A2A JSON-RPC 2.0 wire format, and using the local-mode facade to dispatch
operations directly to application services.

## Prerequisites

- CleverAgents installed (`pip install cleveragents`)
- Python 3.12 or higher

## What You'll Learn

- How to **configure a server endpoint** with `agents server connect`
- How to **inspect server connection status** with `agents server status`
- How to **understand the A2A JSON-RPC 2.0 wire format** (request/response/event models)
- How to **use the A2A local-mode facade** to dispatch operations programmatically
- How to **wire real services** into the facade via `get_facade()` and `register_service()`
- How to **handle version negotiation** with `A2aVersionNegotiator`
- How to **validate server configuration** with `ServerConnectionConfig`

---

## Part 1: Server Connection CLI

### Step 1: Explore the server subcommand

```bash
$ agents server --help
```

**Output:**
```
 Usage: agents server [OPTIONS] COMMAND [ARGS]...

 Server connection management (stub)

╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --help          Show this message and exit.                                  │
╰──────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ connect  Connect to a CleverAgents server (stub).                            │
│ status   Show current server connection status.                              │
│ serve    Run the CleverAgents ASGI server process.                           │
╰──────────────────────────────────────────────────────────────────────────────╯
```

**What's Happening:**

The `server` subcommand has three commands:
- `connect` — registers a server URL in the configuration
- `status` — shows the current server mode and configured URL
- `serve` — launches the ASGI server process (for container/Kubernetes deployments)

---

### Step 2: Check server status before configuration

```bash
$ agents server status
```

**Output:**
```
╭─────── Server Status ────────╮
│ Server Mode: disabled        │
│ Server URL: (not configured) │
│ Namespace: default           │
│ TLS Verify: True             │
╰──────────────────────────────╯
```

**Output (JSON format):**
```bash
$ agents server status --format json
```
```json
{
  "command": "",
  "status": "ok",
  "exit_code": 0,
  "data": {
    "server_mode": "disabled",
    "server_url": null,
    "namespace": "default",
    "tls_verify": true
  },
  "timing": {
    "duration_ms": 0
  },
  "messages": [
    {
      "level": "ok",
      "text": "ok"
    }
  ]
}
```

**What's Happening:**

`server_mode: "disabled"` means no server URL has been configured. The system
operates in local mode — all operations are handled by in-process services.

---

### Step 3: Connect to a server

```bash
$ agents server connect https://agents.example.com
```

**Output:**
```
╭────────────────────────── Server Connection (Stub) ──────────────────────────╮
│ Server URL: https://agents.example.com                                       │
│ Namespace: default                                                           │
│ TLS Verify: True                                                             │
│ Status: stubbed                                                              │
│                                                                              │
│ Server connection is not yet implemented. The URL has been saved to          │
│ configuration but no connection will be made.                                │
╰──────────────────────────────────────────────────────────────────────────────╯
```

**Output (JSON format):**
```bash
$ agents server connect https://agents.example.com --format json
```
```json
{
  "command": "",
  "status": "ok",
  "exit_code": 0,
  "data": {
    "server_url": "https://agents.example.com",
    "namespace": "default",
    "tls_verify": true,
    "status": "stubbed",
    "warning": "Server connection is not yet implemented. The URL has been saved to configuration but no connection will be made."
  },
  "timing": {
    "duration_ms": 0
  },
  "messages": [
    {
      "level": "ok",
      "text": "ok"
    }
  ]
}
```

**What's Happening:**

The `connect` command validates the URL (must start with `http://` or `https://`),
then persists three settings to `~/.cleveragents/config.toml`:
- `server.url` — the server endpoint
- `server.namespace` — the namespace (default: `"default"`)
- `server.tls-verify` — whether to verify TLS certificates (default: `true`)

Each setting change emits a `CONFIG_CHANGED` audit event, ensuring a full audit
trail for these security-relevant settings.

---

### Step 4: Connect with a custom namespace

```bash
$ agents server connect https://agents.example.com --namespace my-team --format json
```

**Output:**
```json
{
  "command": "",
  "status": "ok",
  "exit_code": 0,
  "data": {
    "server_url": "https://agents.example.com",
    "namespace": "my-team",
    "tls_verify": true,
    "status": "stubbed",
    "warning": "Server connection is not yet implemented. The URL has been saved to configuration but no connection will be made."
  },
  "timing": {
    "duration_ms": 0
  },
  "messages": [
    {
      "level": "ok",
      "text": "ok"
    }
  ]
}
```

**What's Happening:**

The `--namespace` (or `-n`) flag sets the namespace on the server. Namespaces
allow multiple teams or projects to share a single CleverAgents server instance
with isolated resources.

---

### Step 5: Connect to a local dev server (no TLS)

```bash
$ agents server connect http://localhost:8080 --no-tls-verify --format json
```

**Output:**
```json
{
  "command": "",
  "status": "ok",
  "exit_code": 0,
  "data": {
    "server_url": "http://localhost:8080",
    "namespace": "default",
    "tls_verify": false,
    "status": "stubbed",
    "warning": "Server connection is not yet implemented. The URL has been saved to configuration but no connection will be made."
  },
  "timing": {
    "duration_ms": 0
  },
  "messages": [
    {
      "level": "ok",
      "text": "ok"
    }
  ]
}
```

**What's Happening:**

`--no-tls-verify` disables certificate verification — useful for local
development with self-signed certificates. Never use this in production.

---

### Step 6: Check status after connecting

```bash
$ agents server status
```

**Output:**
```
╭──────────── Server Status ─────────────╮
│ Server Mode: stubbed                   │
│ Server URL: https://agents.example.com │
│ Namespace: default                     │
│ TLS Verify: True                       │
╰────────────────────────────────────────╯
```

**Output (YAML format):**
```bash
$ agents server status --format yaml
```
```yaml
command: ''
status: ok
exit_code: 0
data:
  server_mode: stubbed
  server_url: https://agents.example.com
  namespace: default
  tls_verify: true
timing:
  duration_ms: 0
messages:
- level: ok
  text: ok
```

**Output (plain format):**
```bash
$ agents server status --format plain
```
```
server_mode: stubbed
server_url: https://agents.example.com
namespace: default
tls_verify: True
```

**What's Happening:**

`server_mode: "stubbed"` means a URL is configured but the actual network
client is not yet implemented. The two possible modes are:

| Mode       | Meaning                                                        |
|------------|----------------------------------------------------------------|
| `disabled` | No server URL configured — local mode only                     |
| `stubbed`  | URL configured, but network client not yet implemented         |

---

### Step 7: Validation — invalid URL rejected

```bash
$ agents server connect not-a-url --format json
```

**Output (exit code 1):**
```
Invalid server configuration: 1 validation error for ServerConnectionConfig
server_url
  Value error, server_url must start with http:// or https://
```

**What's Happening:**

The `connect` command validates the URL using `ServerConnectionConfig` (a
Pydantic model) before writing anything to disk. Invalid URLs are rejected
immediately with a clear error message and exit code 1.

---

### Step 8: Explore the `serve` command options

```bash
$ agents server serve --help
```

**Output:**
```
 Usage: agents server serve [OPTIONS]

 Run the CleverAgents ASGI server process.

 This command is used by container runtimes (Docker/Kubernetes) to launch
 the server endpoint using the project CLI entrypoint (`python -m
 cleveragents`).

╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --host             TEXT                         Bind address for the ASGI    │
│                                                 server                       │
│                                                 [default: 0.0.0.0]           │
│ --port             INTEGER RANGE [1<=x<=65535]  Bind port for the ASGI       │
│                                                 server                       │
│                                                 [default: 8000]              │
│ --workers          INTEGER RANGE [x>=1]         Number of uvicorn worker     │
│                                                 processes                    │
│                                                 [default: 1]                 │
│ --log-level        TEXT                         Uvicorn log level            │
│                                                 [default: info]              │
│ --app              TEXT                         ASGI app import path         │
│                                                 (module:attribute)           │
│                                                 [default:                    │
│                                                 cleveragents.a2a.asgi:app]   │
│ --help                                          Show this message and exit.  │
╰──────────────────────────────────────────────────────────────────────────────╯
```

**What's Happening:**

The `serve` command launches the ASGI server (via `uvicorn`) for container
deployments. The default app target is `cleveragents.a2a.asgi:app`, which
serves health/readiness probes at `/live`, `/ready`, `/health`, and `/`.

---

## Part 2: A2A Protocol Facade

The A2A (Agent-to-Agent) protocol is CleverAgents' internal communication
protocol, based on **JSON-RPC 2.0**. In local mode, the `A2aLocalFacade`
routes operations directly to application services — no network, no
serialization overhead.

### Step 9: Understand the wire format

```python
from cleveragents.a2a.models import A2aRequest, A2aResponse, A2aErrorDetail, A2aEvent

# A2A request — JSON-RPC 2.0 envelope
req = A2aRequest(method="_cleveragents/health/check", params={"key": "value"})
print(req.model_dump())
```

**Output:**
```json
{
  "jsonrpc": "2.0",
  "id": "01KNM6HBGXEZZ6RK37EXCB1AHM",
  "method": "_cleveragents/health/check",
  "params": {
    "key": "value"
  }
}
```

```python
# Successful response
resp = A2aResponse(id=req.id, result={"status": "healthy", "services": {}})
print(resp.model_dump())
```

**Output:**
```json
{
  "jsonrpc": "2.0",
  "id": "01KNM6HBGXEZZ6RK37EXCB1AHM",
  "result": {
    "status": "healthy",
    "services": {}
  },
  "error": null
}
```

```python
# Error response
err_resp = A2aResponse(
    id=req.id,
    error=A2aErrorDetail(code=-32601, message="Method not found")
)
print(err_resp.model_dump())
```

**Output:**
```json
{
  "jsonrpc": "2.0",
  "id": "01KNM6HBGXEZZ6RK37EXCB1AHM",
  "result": null,
  "error": {
    "code": -32601,
    "message": "Method not found",
    "data": {}
  }
}
```

```python
# Server-sent event (for plan progress streaming)
event = A2aEvent(
    event_type="plan.progress",
    plan_id="plan-123",
    data={"phase": "running", "progress": 0.5}
)
print(event.model_dump())
```

**Output:**
```json
{
  "event_id": "01KNM6HBGXEZZ6RK37EXCB1AHN",
  "event_type": "plan.progress",
  "plan_id": "plan-123",
  "data": {
    "phase": "running",
    "progress": 0.5
  },
  "timestamp": "2026-04-07T14:46:24.029773+00:00"
}
```

**What's Happening:**

The A2A wire format follows **JSON-RPC 2.0**:
- `jsonrpc: "2.0"` — always present, validated on construction
- `id` — auto-generated ULID if not provided (sortable, time-ordered)
- `method` — the operation name (e.g. `_cleveragents/plan/status`)
- `params` — operation-specific parameters dict
- `result` XOR `error` — exactly one must be set in responses

`A2aEvent` is used for server-sent events (SSE) during plan execution streaming.

---

### Step 10: List all supported A2A operations

```python
from cleveragents.a2a.facade import A2aLocalFacade

facade = A2aLocalFacade()
ops = facade.list_operations()
print(f"Total operations: {len(ops)}")
for op in ops:
    print(f"  {op}")
```

**Output:**
```
Total operations: 42
  _cleveragents/plan/use
  _cleveragents/plan/execute
  _cleveragents/plan/apply
  _cleveragents/plan/cancel
  _cleveragents/plan/status
  _cleveragents/plan/tree
  _cleveragents/plan/explain
  _cleveragents/plan/correct
  _cleveragents/plan/diff
  _cleveragents/plan/artifacts
  _cleveragents/plan/prompt
  _cleveragents/plan/rollback
  _cleveragents/plan/list
  _cleveragents/registry/tool/list
  _cleveragents/registry/resource/list
  _cleveragents/registry/actor/list
  _cleveragents/registry/skill/list
  _cleveragents/registry/action/list
  _cleveragents/registry/project/list
  _cleveragents/context/show
  _cleveragents/context/inspect
  _cleveragents/context/simulate
  _cleveragents/context/set
  _cleveragents/health/check
  _cleveragents/diagnostics/run
  _cleveragents/sync/pull
  _cleveragents/sync/push
  _cleveragents/sync/status
  _cleveragents/namespace/list
  _cleveragents/namespace/show
  _cleveragents/namespace/members
  session.create
  session.close
  plan.create
  plan.execute
  plan.status
  plan.diff
  plan.apply
  registry.list_tools
  registry.list_resources
  context.get
  event.subscribe
```

**What's Happening:**

The 42 operations fall into two groups:
- **`_cleveragents/` extension methods** (31 ops) — spec-aligned ADR-047 names
  for the current API surface
- **Legacy proprietary names** (11 ops) — deprecated names kept for backward
  compatibility (e.g. `session.create`, `plan.execute`)

The extension methods are organized into namespaces: `plan/`, `registry/`,
`context/`, `health/`, `diagnostics/`, `sync/`, and `namespace/`.

---

### Step 11: Dispatch operations in stub mode (no services)

```python
from cleveragents.a2a.facade import A2aLocalFacade
from cleveragents.a2a.models import A2aRequest

facade = A2aLocalFacade()  # No services wired

def call(method, params=None):
    req = A2aRequest(method=method, params=params or {})
    return facade.dispatch(req)

# Health check
resp = call("_cleveragents/health/check")
print(resp.result)
# → {"status": "healthy", "services": {}}

# Plan list (stub — no service)
resp = call("_cleveragents/plan/list")
print(resp.result)
# → {"plans": [], "stub": true}

# Session create (stub — generates a ULID)
resp = call("session.create", {"actor_name": "test-actor"})
print(resp.result)
# → {"session_id": "01KNM6GE0WQ2TP4X3R0HAF03MJ", "status": "created"}

# Event subscribe (stub)
resp = call("event.subscribe")
print(resp.result)
# → {"subscription_id": "01KNM6GE0WQ2TP4X3R0HAF03MM", "status": "subscribed"}
```

**What's Happening:**

When no services are wired, the facade returns **safe stub responses** for every
operation. This means:
- Operations never crash due to missing dependencies
- Tests can run without a full application container
- The facade is safe to use in minimal environments

---

### Step 12: Dispatch plan lifecycle operations

```python
# Plan create (stub)
resp = call("_cleveragents/plan/use", {"action_name": "my-action"})
print(resp.result)
# → {"plan_id": "01KNM6GYV01AMVWFD1B9YD04MM", "status": "created"}

# Plan status (stub)
resp = call("_cleveragents/plan/status", {"plan_id": "test-plan-123"})
print(resp.result)
# → {"plan_id": "test-plan-123", "phase": "unknown"}

# Plan cancel (stub)
resp = call("_cleveragents/plan/cancel", {"plan_id": "test-plan-123"})
print(resp.result)
# → {"plan_id": "test-plan-123", "status": "cancelled", "stub": true}

# Plan prompt — inject guidance mid-execution
resp = call("_cleveragents/plan/prompt", {
    "plan_id": "test-plan-123",
    "guidance": "Focus on security"
})
print(resp.result)
# → {"plan_id": "test-plan-123", "guidance": "Focus on security",
#    "status": "guidance_injected", "stub": true}

# Plan rollback
resp = call("_cleveragents/plan/rollback", {"plan_id": "test-plan-123"})
print(resp.result)
# → {"plan_id": "test-plan-123", "status": "rolled_back", "stub": true}
```

**What's Happening:**

The plan lifecycle operations map to the full plan state machine:
`use` → `execute` → `apply` (or `cancel`/`rollback`). The `prompt` operation
allows injecting human guidance into a running plan mid-execution — a key
feature of the supervised automation model.

---

### Step 13: Register real services and dispatch

```python
from cleveragents.a2a.facade import A2aLocalFacade
from cleveragents.a2a.models import A2aRequest

facade = A2aLocalFacade()

# Register a mock tool registry
class MockToolRegistry:
    def list_tools(self, namespace=None):
        class Tool:
            name = "bash"
            description = "Run shell commands"
        class Tool2:
            name = "file_read"
            description = "Read file contents"
        return [Tool(), Tool2()]

facade.register_service("tool_registry", MockToolRegistry())

# Now tool list returns real data
req = A2aRequest(method="_cleveragents/registry/tool/list")
resp = facade.dispatch(req)
print(resp.result)
```

**Output:**
```json
{
  "tools": [
    {"name": "bash", "description": "Run shell commands"},
    {"name": "file_read", "description": "Read file contents"}
  ]
}
```

```python
# Register a mock resource registry
class MockResourceRegistry:
    def list_resources(self, type_name=None):
        class R:
            resource_id = "res-001"
            name = "main-repo"
            resource_type_name = "git_repository"
        return [R()]

facade.register_service("resource_registry_service", MockResourceRegistry())

req2 = A2aRequest(method="_cleveragents/registry/resource/list")
resp2 = facade.dispatch(req2)
print(resp2.result)
```

**Output:**
```json
{
  "resources": [
    {
      "resource_id": "res-001",
      "name": "main-repo",
      "type_name": "git_repository"
    }
  ]
}
```

**What's Happening:**

`register_service()` wires a named service into the facade. The handler map is
rebuilt on the next dispatch (cached for performance). This pattern allows
incremental wiring — start with no services and add them as they become
available.

---

### Step 14: Use the fully-wired facade via `get_facade()`

```python
from cleveragents.a2a.cli_bootstrap import get_facade
from cleveragents.a2a.models import A2aRequest

# get_facade() wires the facade to the real DI container
facade = get_facade()
print(f"Services wired: {list(facade._services.keys())}")
# → Services wired: ['plan_lifecycle_service', 'session_service',
#                    'resource_registry_service']

# Health check
req = A2aRequest(method="_cleveragents/health/check")
resp = facade.dispatch(req)
print(resp.result)
# → {"status": "healthy", "services": {}}

# Plan list — returns real plans from the database
req2 = A2aRequest(method="_cleveragents/plan/list")
resp2 = facade.dispatch(req2)
print(resp2.result)
```

**Output:**
```json
{
  "plans": [
    {"plan_id": "01KNKK0MQBWQ5NF0BZYKTF4WJP", "phase": "strategize"},
    {"plan_id": "01KNKK0MKCDXGP8Z3PZ88S5GGZ", "phase": "strategize"},
    {"plan_id": "01KNKJZ44ES00VT8JTRKX1HEQA", "phase": "strategize"},
    {"plan_id": "01KNKJZ424C48388RWHW3KY5QZ", "phase": "strategize"}
  ],
  "total": 4
}
```

**What's Happening:**

`get_facade()` is the production entry point. It:
1. Calls `get_container()` to obtain the DI container
2. Wires available services (suppressing errors for missing ones)
3. Caches the facade for the process lifetime

The facade is process-scoped — multiple CLI invocations within the same Python
process share the same wired instance. Call `reset_facade()` to force a rebuild
(useful in tests).

---

### Step 15: Handle unknown operations

```python
from cleveragents.a2a.errors import A2aOperationNotFoundError
from cleveragents.a2a.models import A2aRequest

facade = A2aLocalFacade()

try:
    req = A2aRequest(method="unknown/operation")
    resp = facade.dispatch(req)
except A2aOperationNotFoundError as e:
    print(f"A2aOperationNotFoundError: {e}")
# → A2aOperationNotFoundError: Unknown A2A method: unknown/operation
```

**What's Happening:**

`A2aOperationNotFoundError` is raised (not returned as an error response) for
truly unknown methods. This is intentional — the caller must handle routing
errors explicitly, while domain errors (e.g. plan not found) are returned as
`A2aResponse.error` payloads.

---

## Part 3: Version Negotiation

### Step 16: Negotiate A2A protocol versions

```python
from cleveragents.a2a.versioning import A2aVersionNegotiator

neg = A2aVersionNegotiator()

print(f"Current version: {neg.get_current()}")
# → Current version: 2.0

print(f"Supported versions: {neg.SUPPORTED_VERSIONS}")
# → Supported versions: ('2.0',)

# Negotiate a supported version
result = neg.negotiate("2.0")
print(f"Negotiated: {result}")
# → Negotiated: 2.0

# Check support
print(f"2.0 supported: {neg.is_supported('2.0')}")   # → True
print(f"1.0 supported: {neg.is_supported('1.0')}")   # → False

# Unsupported version raises
try:
    neg.negotiate("1.0")
except Exception as e:
    print(f"Error: {type(e).__name__}: {e}")
# → Error: A2aVersionMismatchError: A2A version '1.0' is not supported
```

**What's Happening:**

`A2aVersionNegotiator` implements the version handshake for the A2A protocol.
Currently only `"2.0"` (JSON-RPC 2.0) is supported. When a client connects
with an incompatible version, `A2aVersionMismatchError` is raised with the
requested version and the list of supported versions — giving the client
enough information to downgrade gracefully.

---

## Part 4: Server Configuration Model

### Step 17: Validate server connection configuration

```python
from cleveragents.a2a.server_config import ServerConnectionConfig

# Production HTTPS config
cfg = ServerConnectionConfig(
    server_url="https://agents.example.com",
    namespace="production"
)
print(cfg.model_dump())
# → {"server_url": "https://agents.example.com", "namespace": "production",
#    "auth_token_ref": null, "tls_verify": true}

# Local dev config (HTTP, no TLS verification)
cfg2 = ServerConnectionConfig(
    server_url="http://localhost:8080",
    namespace="dev",
    tls_verify=False
)
print(cfg2.model_dump())
# → {"server_url": "http://localhost:8080", "namespace": "dev",
#    "auth_token_ref": null, "tls_verify": false}

# With auth token reference (env var name or secret store key)
cfg3 = ServerConnectionConfig(
    server_url="https://agents.company.com",
    namespace="team-alpha",
    auth_token_ref="CLEVERAGENTS_AUTH_TOKEN",
    tls_verify=True
)
print(cfg3.model_dump())
# → {"server_url": "https://agents.company.com", "namespace": "team-alpha",
#    "auth_token_ref": "CLEVERAGENTS_AUTH_TOKEN", "tls_verify": true}
```

**Validation errors:**

```python
# Empty URL
ServerConnectionConfig(server_url="")
# → ValueError: server_url must not be empty

# Missing scheme
ServerConnectionConfig(server_url="agents.example.com")
# → ValueError: server_url must start with http:// or https://

# Empty namespace
ServerConnectionConfig(server_url="https://agents.example.com", namespace="")
# → ValueError: namespace must not be empty
```

**What's Happening:**

`ServerConnectionConfig` is a frozen Pydantic model — immutable after creation.
The `auth_token_ref` field stores a **reference** to an auth token (e.g. an
environment variable name or secret store key), not the token itself. This
keeps secrets out of the configuration file.

---

## Complete Interaction Log

<details>
<summary>Click to see the full verified command sequence</summary>

```
# 1. Explore server subcommand
$ agents server --help
# → 3 commands: connect, status, serve

# 2. Check initial status (no config)
$ agents server status
# → Server Mode: disabled, Server URL: (not configured)

$ agents server status --format json
# → {"server_mode": "disabled", "server_url": null, "namespace": "default", "tls_verify": true}

# 3. Connect to a server
$ agents server connect https://agents.example.com
# → Panel: Server URL, Namespace: default, TLS Verify: True, Status: stubbed

$ agents server connect https://agents.example.com --format json
# → {"server_url": "https://agents.example.com", "namespace": "default",
#    "tls_verify": true, "status": "stubbed", "warning": "..."}

# 4. Connect with namespace
$ agents server connect https://agents.example.com --namespace my-team --format json
# → {"namespace": "my-team", ...}

# 5. Connect to local dev (no TLS)
$ agents server connect http://localhost:8080 --no-tls-verify --format json
# → {"server_url": "http://localhost:8080", "tls_verify": false, ...}

# 6. Check status after connecting
$ agents server status
# → Server Mode: stubbed, Server URL: https://agents.example.com

$ agents server status --format yaml
# → server_mode: stubbed, server_url: https://agents.example.com

$ agents server status --format plain
# → server_mode: stubbed

# 7. Validation: invalid URL
$ agents server connect not-a-url --format json
# → exit 1: "server_url must start with http:// or https://"

# 8. Explore serve command
$ agents server serve --help
# → --host, --port, --workers, --log-level, --app options

# Python A2A facade usage:
# 9. List 42 supported operations
# 10. Dispatch health check → {"status": "healthy", "services": {}}
# 11. Dispatch plan list (stub) → {"plans": [], "stub": true}
# 12. Dispatch session.create → {"session_id": "01K...", "status": "created"}
# 13. Dispatch plan/use → {"plan_id": "01K...", "status": "created"}
# 14. Dispatch plan/cancel → {"status": "cancelled", "stub": true}
# 15. Dispatch plan/prompt → {"status": "guidance_injected", "stub": true}
# 16. Register MockToolRegistry → tools: [bash, file_read]
# 17. Register MockResourceRegistry → resources: [main-repo]
# 18. get_facade() → wired to real container, plan list returns 4 real plans
# 19. Unknown operation → A2aOperationNotFoundError
# 20. Version negotiation: 2.0 → OK, 1.0 → A2aVersionMismatchError
# 21. ServerConnectionConfig validation: empty URL, no scheme, empty namespace
```
</details>

---

## Key Takeaways

- **Two server modes**: `disabled` (no URL configured) and `stubbed` (URL
  configured, network client pending). The mode is reflected in every
  `server status` response.
- **Config is persisted via audit trail**: `server connect` uses `set_value()`
  (not `write_config()`) so every change emits a `CONFIG_CHANGED` event —
  important for security-relevant settings like server URL and TLS verification.
- **A2A uses JSON-RPC 2.0**: The wire format is standard — `jsonrpc: "2.0"`,
  auto-generated ULID `id`, `method`, `params`, and `result` XOR `error`.
- **42 operations in two groups**: `_cleveragents/` extension methods (spec-
  aligned, ADR-047) and legacy proprietary names (deprecated, kept for backward
  compatibility).
- **Stub-safe facade**: When services are absent, every operation returns a
  safe stub response. The facade never crashes due to missing wiring.
- **`get_facade()` is the production entry point**: It wires the facade to the
  real DI container and caches it for the process lifetime. Use `reset_facade()`
  in tests.
- **`A2aOperationNotFoundError` is raised, not returned**: Unknown methods raise
  an exception; domain errors (plan not found, etc.) are returned as
  `A2aResponse.error` payloads.
- **Version negotiation is strict**: Only `"2.0"` is supported. Clients with
  incompatible versions receive `A2aVersionMismatchError` with enough context
  to downgrade.

## Try It Yourself

```bash
# Check current server mode
$ agents server status --format json | jq '.data.server_mode'

# Connect to a server and immediately check status
$ agents server connect https://my-agents-server.com --namespace my-project
$ agents server status

# Reset server configuration
$ agents config set server.url "" --scope global

# List all A2A operations from Python
$ python -c "
from cleveragents.a2a.facade import A2aLocalFacade
f = A2aLocalFacade()
for op in f.list_operations():
    print(op)
"

# Run a health check via the wired facade
$ python -c "
from cleveragents.a2a.cli_bootstrap import get_facade
from cleveragents.a2a.models import A2aRequest
import json
facade = get_facade()
resp = facade.dispatch(A2aRequest(method='_cleveragents/health/check'))
print(json.dumps(resp.result, indent=2))
"

# Launch the ASGI server for local testing (requires uvicorn)
$ agents server serve --host 127.0.0.1 --port 8080 --log-level debug
```

## Related Examples

- See [`config-and-automation-profiles.md`](config-and-automation-profiles.md)
  for the full guide to configuration management and the five-level resolution chain
- See [`output-format-flags.md`](output-format-flags.md) for the complete guide
  to `--format json/yaml/plain/table/rich`
- See `docs/showcase/cli-tools/` for more CLI tool examples

---
*This example was automatically generated and verified by the CleverAgents UAT system.*
*Feature area: Server and A2A integration | Test cycle: 1 | Generated: 2026-04-07*

---
**Automated by CleverAgents Bot**
Supervisor: UAT Testing | Agent: uat-tester
