# Communication Protocols

TnsAI provides annotation-driven inter-agent communication through `ProtocolManager`. Annotate your agent class with one or more communication paradigms and the framework auto-configures handlers, transports, and discovery.

## ProtocolManager

`ProtocolManager` is the central hub created during agent initialization. It scans annotations on the agent class, creates the matching protocol handlers, and provides a unified messaging API.

```java
// ProtocolManager is accessed via the agent
ProtocolManager pm = agent.getProtocolManager();

// Check what paradigms are active
Set<String> paradigms = pm.getParadigms(); // e.g. ["DIRECT", "PUBSUB"]
boolean hasBroadcast = pm.hasParadigm("BROADCAST");
```

Lifecycle: created in Agent constructor, auto-started if annotations present, stopped when the agent terminates.

## Five Communication Paradigms

TnsAI supports five ways for agents to talk to each other, from simple point-to-point messages to multi-agent debates. You choose a paradigm by adding the matching annotation to your agent class.

| Paradigm | Annotation | Handler | Pattern | Returns Response |
|---|---|---|---|---|
| DirectMessage | `@DirectMessage` | `DirectMessageHandler` | Point-to-point | Yes |
| Broadcast | `@Broadcast` | `BroadcastHandler` | One-to-many (single topic) | No |
| PubSub | `@PubSub` | `PubSubHandler` | Multi-topic subscribe/publish | No |
| RequestReply | `@RequestReply` | `RequestReplyHandler` | Synchronous with timeout | Yes |
| Debate | `@Debate` | `DebateProtocolHandler` | Multi-agent deliberation | No (async) |

### DirectMessage

Point-to-point messaging. Supports both structured action execution and natural language LLM-powered messaging.

```java
@DirectMessage
public class OrderAgent extends Agent { }

// Structured action execution
Message response = pm.executeAction("receiver-id", "processOrder", Map.of(
    "orderId", "12345"
));

// With role targeting
Message response = pm.executeAction("receiver-id", "billing-role", "charge", params);

// Natural language (receiver's LLM parses and responds)
Message reply = pm.sendMessage("receiver-id", "Please summarize the quarterly report");
```

### Broadcast

One-to-many messaging on a single topic. Automatically discovers and delivers to all agents subscribed to the topic.

```java
@Broadcast(topic = "system-alerts", canSubscribe = true)
public class MonitorAgent extends Agent { }

// Broadcast to all subscribers
pm.broadcast(Map.of("level", "HIGH", "message", "CPU threshold exceeded"));
```

Agents with `canSubscribe = false` can publish but will not receive broadcasts.

### PubSub

Multi-topic publish/subscribe. Similar to Broadcast but supports multiple topics per agent and per-topic subscriber management.

```java
@PubSub(topics = {"alerts", "metrics", "deployments"})
public class DashboardAgent extends Agent { }

// Publish to a specific topic
pm.publish("alerts", Map.of("severity", "WARN", "source", "db-pool"));
pm.publish("metrics", Map.of("cpu", 85.2, "memory", 72.1));
```

The `PubSubHandler` tracks delivery results via `PublishResult`:

```java
PubSubHandler handler = ...;
PubSubHandler.PublishResult result = handler.getLastPublishResult();
// result.successCount(), result.failCount(), result.isFullyDelivered()
```

### RequestReply

Synchronous request-response with configurable timeout. Blocks the caller until a reply arrives or timeout is reached.

```java
@RequestReply(timeout = 30000) // 30 second timeout
public class QueryAgent extends Agent { }

// Send request and wait for reply
Message reply = pm.request("data-agent", "fetchReport", Map.of(
    "quarter", "Q4",
    "year", 2025
));
```

The handler manages a `CompletableFuture` per pending request and completes it when the reply arrives via `handleReply()`.

### Debate

Multi-agent deliberation protocol with round-based discussion, position submission, voting, and consensus detection.

```java
@Debate(maxRounds = 5, consensusThreshold = 0.66,
        strategy = Debate.ConsensusStrategy.WEIGHTED_CONFIDENCE,
        roundTimeoutMs = 60000)
public class DecisionAgent extends Agent { }

// Start a debate
DebateSession session = pm.startDebate(
    "Should we deploy to production?",
    List.of("dev-agent", "qa-agent", "ops-agent")
);

// Submit position (stance, confidence 1-10, reasoning)
pm.submitDebatePosition(session.getId(), "YES", 8, "All tests pass, staging looks good");

// Vote on another's position
pm.voteInDebate(session.getId(), "NO", false);

// Submit counter-argument
pm.counterArgument(session.getId(), "ops-agent",
    "Staging does not reflect prod traffic patterns", "Wait for load test results");
```

Consensus strategies: `MAJORITY`, `SUPERMAJORITY`, `UNANIMOUS`, `WEIGHTED_CONFIDENCE`. When consensus threshold is met, `DebateStatus.CONSENSUS` is set. If max rounds are exhausted without consensus, `DebateStatus.DEADLOCK` falls back to the highest-support stance.

## FIPA Protocols

FIPA (Foundation for Intelligent Physical Agents) is an international standard for agent communication. TnsAI implements these standards so your agents can interact using well-defined message types and interaction patterns recognized across the multi-agent systems community. The `com.tnsai.protocols.fipa` package provides FIPA ACL (Agent Communication Language) compliant messaging.

### FIPAPerformative

A performative describes the intent of a message -- whether the sender is informing, requesting, proposing, or refusing. TnsAI supports all 21 FIPA performatives organized by category:

| Category | Performatives |
|---|---|
| Assertive | `INFORM`, `CONFIRM`, `DISCONFIRM`, `INFORM_IF`, `INFORM_REF` |
| Directive | `REQUEST`, `REQUEST_WHEN`, `REQUEST_WHENEVER`, `QUERY_REF`, `QUERY_IF`, `SUBSCRIBE` |
| Commissive | `PROPOSE`, `ACCEPT_PROPOSAL`, `REJECT_PROPOSAL`, `AGREE`, `REFUSE`, `CFP` |
| Declarative | `CANCEL`, `FAILURE`, `NOT_UNDERSTOOD`, `PROPAGATE`, `PROXY` |

Each performative knows whether it is initiating (`isInitiating()`), responding (`isResponding()`), positive (`isPositive()`), or negative (`isNegative()`).

### FIPAMessage Builder

`FIPAMessage` is the structured message object that agents exchange. It is a Java record with a fluent builder and includes all standard FIPA ACL fields such as sender, receiver, content, protocol, and ontology.

```java
// Build a request message
FIPAMessage request = FIPAMessage.builder()
    .performative(FIPAPerformative.REQUEST)
    .sender("agent-1")
    .receiver("agent-2")
    .content("Please perform analysis")
    .protocol("fipa-request")
    .ontology("market-analysis")
    .replyBy(Instant.now().plus(Duration.ofMinutes(5)))
    .build();

// Create a reply from an existing message
FIPAMessage reply = request.createReply()
    .performative(FIPAPerformative.AGREE)
    .content("I will perform the analysis")
    .build();

// Convenience factory methods
FIPAMessage inform = FIPAMessage.inform("sender", "receiver", "Task complete");
FIPAMessage cfp = FIPAMessage.cfp("manager", "worker", "Translate document to French");
FIPAMessage query = FIPAMessage.queryIf("agent-a", "agent-b", "Is the service healthy?");
```

Key message utilities: `expectsReply()`, `isReply()`, `isReplyOverdue()`.

### ContractNetProtocol

The Contract Net protocol is a standard way to delegate tasks through competitive bidding: a manager broadcasts a "call for proposals," agents submit bids, and the manager picks the best one. It implements the FIPA Contract Net interaction protocol for task delegation through competitive bidding.

```java
ContractNetProtocol protocol = new ContractNetProtocol();

// Initiator creates CFP
FIPAMessage cfp = protocol.createCFP("manager", "Translate 500 pages to French");
protocol.processMessage(cfp);

// Participants respond with proposals
FIPAMessage proposal = protocol.createProposal(cfp, "Can do in 2 days for $500");
protocol.processMessage(proposal);

// Initiator selects winner
protocol.selectProposal("translator-agent");
FIPAMessage acceptance = protocol.createAcceptance(proposal);
protocol.processMessage(acceptance);

// Check state
protocol.isComplete();    // false until INFORM or FAILURE
protocol.isSuccessful();  // true after INFORM
protocol.getProposals();  // map of sender -> proposal
```

Protocol state machine: `INITIAL` -> `AWAITING_RESPONSE` -> `NEGOTIATING` -> `COMPLETED_SUCCESS` / `COMPLETED_FAILURE`.

## Transport Modes

Transport modes control how messages are physically delivered between agents. Agents in the same JVM use fast in-memory transport, while remote agents communicate over HTTP. Each protocol handler uses a `Transport` implementation for message delivery.

| Mode | Class | Use Case |
|---|---|---|
| `INTERNAL` | `InternalTransport` | Same JVM, in-memory (fastest) |
| `HTTP` | `HttpTransport` | Remote agents via HTTP/REST |
| `AUTO` | (resolved) | Auto-selects based on endpoint config |

```java
// Transport is configured via annotation attributes
@DirectMessage(endpoint = "http://remote:8080", transport = TransportMode.HTTP)
public class RemoteAgent extends Agent { }

// Internal transport (default when no endpoint specified)
@DirectMessage(transport = TransportMode.INTERNAL)
public class LocalAgent extends Agent { }

// Auto mode: resolves to INTERNAL if no endpoint, HTTP if endpoint given
@DirectMessage(transport = TransportMode.AUTO)
public class FlexibleAgent extends Agent { }
```

The `Transport` interface provides `send()` (synchronous), `sendAsync()` (callback-based), and `isSynchronous()` to let handlers decide whether to use futures for reply correlation.
