Skip to content
92 changes: 54 additions & 38 deletions content/Guides/agent-communication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ description: Agent-to-Agent communication patterns, usage and best practices

import Image from "next/image";

<Image src="/images/agent-to-agent.png" alt="Agent-to-AgentCommunication" width={640} height={640} />
<Image src="/images/agent-to-agent.png" alt="Agent-to-Agent Communication" width={640} height={640} />

### How do agents communicate with each other?
## Overview

In most advanced agentic scenarios, agents need to communicate with other agents to achieve their goals.

In fact, our recommendation is that you build agents with highly specialized roles and skills and use agent-to-agent communication to achieve the overall goal.
In most advanced agentic scenarios, agents need to communicate with other agents to achieve their goals. In fact, our recommendation is that you build agents with highly specialized roles and skills and use agent-to-agent communication to achieve the overall goal.

There are a number of ways to achieve agent-to-agent communication natively in Agentuity.

#### Communication Types
## Communication Types

Agents can communicate with each other in a number of ways in the Agentuity platform. The following are the different types of communication that are supported:

Expand All @@ -25,28 +23,28 @@ Agents can communicate with each other in a number of ways in the Agentuity plat
| **Inter Project** | Agents can communicate with each other across projects within the same organization across the internal network |
| **Inter Organization** | Agents can communicate with each other across organizations across the internal network |

##### Intra Project
### Intra Project

Intra project communication is the simplest form of agent-to-agent communication. Agents within the same project can communicate with each other locally without leaving the local network.

##### Inter Project
### Inter Project

Inter project communication is a more advanced form of agent-to-agent communication. Agents can communicate with each other across projects within the same organization but will communicate over the internal network.

##### Inter Organization
### Inter Organization

Inter organization communication is the most advanced form of agent-to-agent communication. Agents can communicate with each other across organizations. Currently, Agentuity only supports inter organization agent communication if the target agent is public and the source agent has been given the agent ID by the other organization. For inter organization communication, the source agent will communicate over the internal network.

#### Communication Methods
## Communication Methods

Agents has two primary methods of communication with other agents:
Agents have two primary methods of communication with other agents:

| Type | Description |
|-----------|-------------|
| Handoff | Agents can handoff a request to another agent to complete |
| Invocation | Agents can invoke another agent to complete a task and wait for the result |

##### Handoff
### Handoff

When an agent needs to handoff a request to another agent, it can do so by using the SDK `handoff` method. The `handoff` method will send the request to another agent and the other agent will be responsible for completing the request.

Expand Down Expand Up @@ -81,20 +79,24 @@ export default async function Agent(
resp: AgentResponse,
ctx: AgentContext
) {
return resp.handoff({name: 'My Other Agent'}, "would you please do this?");
return resp.handoff(
{name: 'My Other Agent'},
{ data: "would you please do this?", contentType: "text/plain" }
);
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext

async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
# Python infers: string → text/plain, dict → application/json
return response.handoff({"name":"My Other Agent"}, "would you please do this?")
`} />

##### Invocation
### Invocation

When an agent needs to invoke another agent to complete a task and wants to wait for the result, it can do so by using the SDK `getAgents` method on `AgentContext`. The `getAgents` will perform resolution to determine the target agent location and return a handle to the target agent that can be used to `run` the target agent.
When an agent needs to invoke another agent to complete a task and wants to wait for the result, it can do so by using the SDK `getAgent` method on `AgentContext`. The `getAgent` will perform resolution to determine the target agent location and return a handle to the target agent that can be used to `run` the target agent.

If the target agent is local (intra project), the `getAgents` method will return a handle to an internal agent which can be used to `run` the target agent.
If the target agent is local (intra project), the `getAgent` method will return a handle to an internal agent which can be used to `run` the target agent.

If the target agent is remote (inter project or inter organization), the `getAgents` method will return a handle to an external agent which can be used to `run` the target agent. In addition, the SDK internally will use the authorization token to authenticate the source agent to the target agent.
If the target agent is remote (inter project or inter organization), the `getAgent` method will return a handle to an external agent which can be used to `run` the target agent. In addition, the SDK internally will use the authorization token to authenticate the source agent to the target agent.

<Mermaid chart="
sequenceDiagram
Expand All @@ -115,23 +117,31 @@ export default async function Agent(
ctx: AgentContext
) {
const agent = await ctx.getAgent({name: 'My Other Agent'});
const agentResponse = await agent.run({name: 'My Other Agent'}, "would you please do this?");
// Basic usage - perfect for simple string data
const agentResponse = await agent.run({ data: "would you please do this?" });
// Explicit control when needed:
// const agentResponse = await agent.run({ data: "would you please do this?", contentType: "text/plain" });
const text = await agentResponse.data.text();
return resp.text(text);
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext

async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
agent = await context.getAgent({"name":"My Other Agent"})
agent_response = await agent.run({"name":"My Other Agent"}, "would you please do this?")
agent = await context.get_agent({"name":"My Other Agent"})
# Send plain text (content type inferred as text/plain)
agent_response = await agent.run("would you please do this?")
# Or send JSON (content type inferred as application/json)
# agent_response = await agent.run({"message": "would you please do this?"})
text = await agent_response.data.text()
return response.text(text)
`} />

> **Note:** JavaScript uses `{ data, contentType }` format while Python infers content type from the raw payload passed directly.

In this trivial example above, the functionality is similar to the handoff example above. The source agent is sending a request to the `My Other Agent` agent and passing a message to the other agent. The `My Other Agent` agent will receive the request, perform an operation and return the result to the source agent. The source agent will simply return the result as a text result.

In a real life scenario, you'll likely want to pass the appropriate data types to the target agent and wait for the result and then use the result in your own agent to perform additional tasks.

###### Parallel Execution
#### Parallel Execution

Sometimes you want to send a request to multiple agents at the same time. This is an example of parallel execution.

Expand All @@ -144,22 +154,28 @@ export default async function Agent(
) {
const agent1 = await ctx.getAgent({name: 'My First Agent'});
const agent2 = await ctx.getAgent({name: 'My Second Agent'});
// Basic usage - perfect for simple object data
await Promise.all([
agent1.run({task: 'My First Task'}),
agent2.run({task: 'My Second Task'}),
agent1.run({ data: { task: 'My First Task' } }),
agent2.run({ data: { task: 'My Second Task' } }),
]);
// Explicit control when needed:
// await Promise.all([
// agent1.run({ data: { task: 'My First Task' }, contentType: 'application/json' }),
// agent2.run({ data: { task: 'My Second Task' }, contentType: 'application/json' }),
// ]);
return resp.text('OK');
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext
import asyncio

async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):

agent1 = await context.getAgent({"name":"My First Agent"})
agent2 = await context.getAgent({"name":"My Second Agent"})
agent1 = await context.get_agent({"name":"My First Agent"})
agent2 = await context.get_agent({"name":"My Second Agent"})

await asyncio.gather(
agent1.run({"task":"My First Task"}),
agent2.run({"task":"My Second Task"}),
agent1.run({"task": "My First Task"}), # content type inferred as JSON
agent2.run({"task": "My Second Task"}), # content type inferred as JSON
)

return response.text('OK')
Expand All @@ -175,27 +191,27 @@ sequenceDiagram
actor Agentuity
actor Agent 2
actor Agent 3
Agent 1-->>Agentuity: Get Agent 1
Agent 1-->>Agentuity: Get Agent 2
Agent 1-->>Agentuity: Get Agent 3
Agent 1->>Agent 2: Run
Agent 1->>Agent 3: Run
"/>

#### Agent Resolution
## Agent Resolution

How do we resolve the target agent? There are two main ways to do this:
How do we resolve the target agent? There are three main ways to do this:

| Type | Description |
|-----------|-------------|
| Agent ID | The agent ID is a unique identifier for an agent. It is a string that is assigned to an agent when it is created. |
| Agent Name | The agent name is a human readable name for an agent. It is a string that was used for the agent's name. |
| Project ID | The agent project ID is specified to disambiguate agents with the same name in different projects. |

##### Intra Project Resolution
### Intra Project Resolution

When calling an agent within the same project, the agent name is usually the easiest way to resolve the target agent. The agent name is a human readable name for an agent. It is a string that was used for the agent's name.

##### Inter Project Resolution
### Inter Project Resolution

When calling an agent across projects within the same organization, the agent ID is typically the most reliable way to resolve the target agent. The agent ID is a unique identifier for an agent.

Expand All @@ -211,23 +227,23 @@ export default async function Agent(
ctx: AgentContext
) {
return resp.handoff({
id: 'agent_123456789abcedef',
projectId: 'project_123456789abcedef',
id: 'agent-123456789abcedef',
projectId: 'project-123456789abcedef',
});
}`} py={`
from agentuity import AgentRequest, AgentResponse, AgentContext

async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
return response.handoff({
"id": "agent_123456789abcedef",
"projectId": "project_123456789abcedef"
"id": "agent-123456789abcedef",
"projectId": "project-123456789abcedef"
})
`} />

##### Inter Organization Resolution
### Inter Organization Resolution

Currently, Agentuity only supports inter organization agent communication if the target agent is public and the source agent has been given the agent ID by the other organization. When using inter organization communication, only the agent ID is required to resolve the target agent.

#### Communication Authorization
## Communication Authorization

When communicating with other agents outside the local project, Agentuity will automatically generate a one-time use authorization token with a short expiration. This token is used to authenticate the source agent to the target agent automatically without the need for the source agent to pass the token to the target agent.
28 changes: 15 additions & 13 deletions content/Guides/agent-data-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ title: Agent Data Handling
description: How to handle data formats in your agents
---

We provide a few different ways to handle data formats in your agents to make it easier to work with different data types. Of course, your agent can always perform its own data handling by use the raw data and the content type property. However, most common data types are supported out of the box.
## Overview

We provide a few different ways to handle data formats in your agents to make it easier to work with different data types. Of course, your agent can always perform its own data handling by using the raw data and the content type property. However, most common data types are supported out of the box.

## How it works

Expand Down Expand Up @@ -37,16 +39,16 @@ export default async function Agent(
}`} py={`from agentuity import AgentRequest, AgentResponse, AgentContext

async def run(request: AgentRequest, response: AgentResponse, context: AgentContext):
contentType = request.data.contentType
if contentType == 'text/plain':
text = await request.data.text()
# do something with the text
elif contentType == 'application/json':
json = await request.data.json()
# do something with the json
else:
# do something with the data
pass
contentType = request.data.contentType
if contentType == 'text/plain':
text = await request.data.text()
# do something with the text
elif contentType == 'application/json':
json = await request.data.json()
# do something with the json
else:
# do something with the data
pass
`} />

## Request Data Formats
Expand All @@ -55,7 +57,7 @@ The following request data formats are supported out of the box:

### Text

You use use the `text` method on the `Data` object to get the raw text data.
You can use the `text` method on the `Data` object to get the raw text data.

<CodeExample js={`import type { AgentContext, AgentRequest, AgentResponse } from '@agentuity/sdk';

Expand Down Expand Up @@ -442,7 +444,7 @@ async def run(request: AgentRequest, response: AgentResponse, context: AgentCont
chat_completion = client.chat.completions.create(
messages=[
{"role": "system", "content": "You are a friendly assistant!"},
{"role": "user", "content": request.data.text or "Why is the sky blue?"},
{"role": "user", "content": (await request.data.text()) or "Why is the sky blue?"},
],
model="gpt-4o",
stream=True,
Expand Down
Loading