# Agent-to-Agent (A2A) Communication Guide

Welcome to the **AgentArea agent-to-agent communication** documentation.  
This feature allows an _agent A_ to request work from _agent B_ by **creating a task for it** via the A2A-protocol API. Under the hood it is powered by:

* **AgentCommunicationService** – orchestration layer that issues tasks and tracks their results  
* **InMemoryTaskManager** – default store used to register the delegated tasks  
* **Google ADK “ask_agent” tool** – automatically injected into your `LlmAgent` so it can call helper agents from within its reasoning chain.

---

## 1. When to Use

| Scenario | Benefit |
|----------|---------|
| Complex workflows that exceed one agent’s skills | Delegate subtasks to specialised helpers. |
| Tool-style agents (e.g. code-generator) need clarification | Ask a “support” agent for domain knowledge. |
| Chained reasoning | Primary agent breaks the problem into steps and dispatches them. |

---

## 2. Architecture Overview

```
Primary Agent ──ask_agent()──► AgentCommunicationService ──► TaskManager
                                               │
                                               ▼
                                EventBroker (TaskCreated / …)
                                               │
                                 Helper Agent Runner picks task
                                               │
                               (work, emit TaskCompleted / Failed)
                                               ▼
                              AgentCommunicationService resolves
```

* **ask_agent tool** → validates input, generates a unique task-id, calls TaskManager (`tasks/send`) with metadata:
  ```json
  {
    "agent_id": "<helper-agent-uuid>",
    "is_agent_to_agent": true
  }
  ```
* **Service** stores an `asyncio.Event` and waits (max configurable 60 s) for TaskCompleted/Failed.
* Result (or error) is transparently returned to the calling agent so it can continue its reasoning.

---

## 3. Prerequisites

* AgentArea backend running (`uvicorn core.agentarea.main:app --reload`)
* **Google ADK** installed (`pip install google-adk`)
* Event broker configured (Redis/Kafka) – required for task status events
* Agents you want to communicate **must exist** in the database (see CLI or REST `/agents/`).

---

## 4. Enabling / Disabling Communication

Global flag is set in `startup.py` when `AgentCommunicationService` is registered.  
Per-run override:

```python
task_execution_service.execute_task_async(
    ...,
    metadata={
        "enable_agent_communication": false   # disable for this task
    }
)
```

If disabled the `ask_agent` tool is **not** injected and direct calls raise `ValueError`.

---

## 5. Using the `ask_agent` Tool (inside an agent)

### Tool specification (autogenerated)

| Name | Type | Description |
|------|------|-------------|
| `agent_id` | string | Helper agent UUID |
| `message`  | string | Instruction for the helper agent |
| `wait_for_response` | boolean (default `true`) | Whether to wait until the helper finishes |
| `metadata` | object (optional) | Extra metadata stored on the delegated task |

Output:

```json
{
  "task_id": "b4f5…",
  "status": "completed",
  "response": "… helper agent reply …"
}
```

### Example Prompt

```
If you cannot solve the maths problem yourself, call ask_agent with:
{
  "agent_id": "77fa25d0-bd50-466c-8599-54f6f61c6d1b",
  "message": "Compute the integral of sin(x)/x from 0 to infinity."
}
```

The library will serialize the call, await completion (if `wait_for_response=true`) and inject the result into the conversation.

---

## 6. Manual Task Creation (REST)

You can simulate the same process via HTTP:

```bash
curl -X POST http://localhost:8000/v1/tasks/ \
  -H "Content-Type: application/json" \
  -d '{
        "message": "Translate this to French: Hello World",
        "agent_id": "77fa25d0-bd50-466c-8599-54f6f61c6d1b",
        "metadata": { "is_agent_to_agent": true }
      }'
```

Track status:

```
GET /v1/tasks/{task_id}
```

---

## 7. Full Example Script

`examples/agent_to_agent_example.py` demonstrates:

1. Creating primary & helper agents  
2. Primary agent delegating a math task  
3. Waiting for completion  
4. Local simulation without backend (Google ADK only)

Run:

```bash
python examples/agent_to_agent_example.py
```

---

## 8. Configuration Options

| Setting | Location | Default | Description |
|---------|----------|---------|-------------|
| `max_wait_time` | `AgentCommunicationService` constructor | `60 s` | Maximum time the primary agent waits for helper completion |
| `enable_agent_communication` | Metadata per task | `null` (_inherits global_) | Force enable/disable on a task basis |
| Event subscriptions | `startup.py` | _auto_ | Service listens to `TaskCompleted` & `TaskFailed` |

---

## 9. Troubleshooting

| Issue | Resolution |
|-------|------------|
| `ValueError: Agent-to-agent communication is disabled` | Enable globally or pass `"enable_agent_communication": true` in task metadata |
| Primary agent waits forever | Increase `max_wait_time` or verify helper agent is running |
| Helper returns no response | Ensure helper agent adds a message or artifact; otherwise default text is returned |

Enable debug logs:

```bash
export LOGLEVEL=debug
```

---

## 10. Security Considerations

* All delegated tasks inherit **user_id** of the caller (if provided) – use RBAC to restrict cross-agent calls.  
* Validate metadata size to avoid abuse.  
* When exposing externally, protect the `/tasks/send` endpoint with authentication.

---

Happy collaborating! Your agents can now talk to each other and share the workload seamlessly.  
For questions join our Discord #agent-to-agent channel.
