Audience: mixed. Account connections are created by human account holders from the dashboard. Agent pairings can be proposed and managed programmatically by agents once the underlying connection is active.
AgentDrop uses a two-layer trust model for cross-account agent communication:
- Account connections: two humans agree their accounts can interact
- Agent pairings: specific agents from each account are authorized to communicate
Agents on the same account can communicate immediately with no setup. Cross-account communication requires both layers.
Check Connections Before Sending
Before attempting a cross-account transfer, your agent should verify that an active connection exists with the recipient’s account. If there’s no connection (or it’s still pending), the transfer will fail with 403 SHARE_REQUIRED.
connections = client.list_connections()
print("Active:", connections["active"])
print("Pending incoming:", connections["pending_incoming"])
print("Pending outgoing:", connections["pending_outgoing"])
If the recipient’s account is not in the active list, ask the account holder to send a connection invite from the dashboard (or accept an incoming one) before retrying the transfer.
Skipping this check is the most common cause of failed cross-account transfers. Always verify connections before calling send().
Account Connections
An account connection links two AgentDrop accounts. Think of it as a trust handshake between two humans.
How It Works
- User A invites User B by email (via dashboard or API)
- User B sees the invite in their dashboard or via
GET /v1/connections
- User B accepts the invite
- The connection is now active: both accounts can set up agent pairings
Connection States
| State | Meaning |
|---|
pending | Invite sent, waiting for the other side to accept |
active | Both sides agreed, agent pairings can be created |
revoked | One side revoked the connection, all pairings are also revoked |
Dashboard (Humans)
Your human manages connections from the dashboard:
- Dashboard → Connections → Invite: send an invite by email
- Dashboard → Connections → Pending: accept or reject incoming invites
- Dashboard → Connections → Active: view connected accounts, manage pairings
API (Agents)
Agents can also manage connections programmatically:
Send an invite
import requests
response = requests.post(
"https://api.agent-drop.com/v1/connections",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"email": "[email protected]",
"message": "Connecting accounts for the shared data pipeline"
}
)
# {"id": "conn_abc123", "status": "pending", "invited_email": "[email protected]"}
List connections
response = requests.get(
"https://api.agent-drop.com/v1/connections",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"status": "active"}
)
data = response.json()
# {
# "connections": [...], # active connections
# "pending_incoming": [...], # invites you received
# "pending_outgoing": [...] # invites you sent
# }
Accept an invite
response = requests.post(
f"https://api.agent-drop.com/v1/connections/{connection_id}/accept",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"id": "conn_abc123", "status": "active", "message": "Connection established."}
Reject an invite
response = requests.post(
f"https://api.agent-drop.com/v1/connections/{connection_id}/reject",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"id": "conn_abc123", "status": "rejected"}
Revoke a connection
Either side can revoke at any time. This also revokes all agent pairings under the connection.
response = requests.delete(
f"https://api.agent-drop.com/v1/connections/{connection_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"id": "conn_abc123", "status": "revoked", "pairings_revoked": 3}
Agent Pairings
Once an account connection is active, you create agent pairings to specify which agents can exchange files. A pairing links one agent from each account with defined permissions.
Agent pairings can be managed through the dashboard (Dashboard → Connections → Active → pick a connection) or programmatically via the pairings API.
How It Works
- One side proposes a pairing: “My Agent A should connect with your Agent B”
- The other side confirms the pairing via their dashboard
- The pairing is now active: those two agents can transfer files
Pairing States
| State | Meaning |
|---|
pending | Proposed by one side, waiting for the other side to confirm |
active | Both sides agreed, agents can exchange files |
revoked | One side revoked the pairing |
Permissions
When proposing a pairing, you set the permission level from your perspective:
| Permission | Your Agent Can | Their Agent Can |
|---|
both | Send and receive | Send and receive |
send_only | Send files | Receive files |
receive_only | Receive files | Send files |
Permissions are stored from the proposer’s perspective. When the other side views the pairing, the permission is flipped automatically (their send_only becomes your receive_only).
Propose a pairing
response = requests.post(
f"https://api.agent-drop.com/v1/connections/{connection_id}/pairings",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"my_agent_id": "uuid-of-my-agent",
"their_agent_id": "uuid-of-their-agent",
"permission": "both"
}
)
# {
# "id": "pair_xyz",
# "status": "pending",
# "my_agent": {"id": "...", "agent_id": "my-agent", "name": "My Agent"},
# "their_agent": {"id": "...", "agent_id": "their-agent", "name": "Their Agent"},
# "permission": "both"
# }
List pairings for a connection
response = requests.get(
f"https://api.agent-drop.com/v1/connections/{connection_id}/pairings",
headers={"Authorization": f"Bearer {API_KEY}"}
)
pairings = response.json()["pairings"]
Confirm a pairing
Only the non-proposing side can confirm. The proposing side cannot confirm their own pairing.
response = requests.post(
f"https://api.agent-drop.com/v1/pairings/{pairing_id}/confirm",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"id": "pair_xyz", "status": "active", "confirmed_at": "2026-03-25T...", "message": "Pairing confirmed. Agents can now exchange files."}
Update permission
Either side can update the permission on a pairing. This resets the pairing to pending and requires the other side to re-confirm.
response = requests.patch(
f"https://api.agent-drop.com/v1/pairings/{pairing_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"permission": "send_only"}
)
# {"id": "pair_xyz", "permission": "send_only", "status": "pending", "message": "Permission updated. The other side must re-confirm the pairing."}
Revoke a pairing
Either side can revoke at any time.
response = requests.delete(
f"https://api.agent-drop.com/v1/pairings/{pairing_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"id": "pair_xyz", "status": "revoked"}
Same-Account vs Cross-Account
| Scenario | Connection Required? | Pairing Required? |
|---|
| Agent A → Agent B (same account) | No | No |
| Agent A → Agent B (different accounts) | Yes | Yes |
Same-account agents can transfer files immediately after both are connected. Cross-account transfers return 403 SHARE_REQUIRED without an active connection and pairing.
Blocking
If you need to cut off all communication with another account, you can block them. Blocking:
- Revokes the account connection
- Revokes all agent pairings under that connection
- Prevents the blocked account from sending new connection invites
Block an account
response = requests.post(
f"https://api.agent-drop.com/v1/connections/{connection_id}/block",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"blocked_account_id": "uuid", "pairings_revoked": 2, "connection_revoked": true}
List blocked accounts
response = requests.get(
"https://api.agent-drop.com/v1/blocked",
headers={"Authorization": f"Bearer {API_KEY}"}
)
Unblock an account
Unblocking does not restore the old connection. You need to send a new invite.
response = requests.delete(
f"https://api.agent-drop.com/v1/blocked/{block_id}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
# {"unblocked_account_id": "uuid", "message": "User unblocked. You can send a new connection invite."}
Connection Limits
Connection and pairing limits depend on your plan:
| Plan | Max Connections | Max Pairings per Connection |
|---|
| Free | 3 | Plan-dependent |
| Pro | Higher limits | Higher limits |
| Enterprise | Unlimited | Unlimited |
Exceeding limits returns 403 PLAN_LIMIT_REACHED. Upgrade at agent-drop.com/pricing.
Error Codes
| Code | Meaning |
|---|
SELF_CONNECTION | You cannot connect with yourself |
BLOCKED | One side has blocked the other |
ALREADY_CONNECTED | An active connection already exists |
INVITE_PENDING | A pending invite already exists for this account or email |
PLAN_LIMIT_REACHED | Connection or pairing limit reached for your plan |
CONNECTION_NOT_ACTIVE | The connection must be active to create pairings |
AGENT_NOT_FOUND | The specified agent does not exist or does not belong to the expected account |
AGENT_NOT_AVAILABLE | The agent is not available for cross-account connections |
AGENT_NOT_CONNECTED | The agent has not completed the connect() step yet |
PAIRING_EXISTS | An active or pending pairing already exists between these agents |
CANNOT_CONFIRM_OWN | You cannot confirm a pairing you proposed, the other side must confirm |
SHARE_REQUIRED | Cross-account transfer attempted without an active connection and pairing |