Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): updates to mailbox and agentverse registration process #588

Merged
merged 18 commits into from
Dec 12, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix: updates to registration response
jrriehl committed Dec 4, 2024
commit fae88ae873b68219c1f1e9506454f91e14a50c05
55 changes: 34 additions & 21 deletions python/src/uagents/agent.py
Original file line number Diff line number Diff line change
@@ -32,14 +32,20 @@
REGISTRATION_RETRY_INTERVAL_SECONDS,
REGISTRATION_UPDATE_INTERVAL_SECONDS,
TESTNET_PREFIX,
AgentverseConfig,
parse_agentverse_config,
parse_endpoint_config,
)
from uagents.context import Context, ContextFactory, ExternalContext, InternalContext
from uagents.crypto import Identity, derive_key_from_seed, is_user_address
from uagents.dispatch import Sink, dispatcher
from uagents.envelope import EnvelopeHistory, EnvelopeHistoryEntry
from uagents.mailbox import MailboxClient
from uagents.mailbox import (
AgentverseUserToken,
MailboxClient,
RegistrationResponse,
register_in_agentverse,
)
from uagents.models import ErrorMessage, Model
from uagents.network import (
InsufficientFundsError,
@@ -212,7 +218,7 @@ class Agent(Sink):
_logger: The logger instance for logging agent activities.
_endpoints (List[AgentEndpoint]): List of endpoints at which the agent is reachable.
_use_mailbox (bool): Indicates if the agent uses a mailbox for communication.
_agentverse (dict): Agentverse configuration settings.
_agentverse (AgentverseConfig): Agentverse configuration settings.
_mailbox_client (MailboxClient): The client for interacting with the agentverse mailbox.
_ledger: The client for interacting with the blockchain ledger.
_almanac_contract: The almanac contract for registering agent addresses to endpoints.
@@ -326,20 +332,20 @@ def __init__(
else:
agentverse = mailbox
self._agentverse = parse_agentverse_config(agentverse)
self._use_mailbox = self._agentverse["use_mailbox"]
self._use_mailbox = self._agentverse.agent_type == "mailbox"
if self._use_mailbox:
self._mailbox_client = MailboxClient(self, self._logger)
self._mailbox_client = MailboxClient(self._agentverse, self._logger)
# if mailbox is provided, override endpoints with mailbox endpoint
self._endpoints = [
AgentEndpoint(
url=f"{self.mailbox['http_prefix']}://{self.mailbox['base_url']}/v1/submit",
weight=1,
)
AgentEndpoint(url=f"{self._agentverse.url}/v1/submit", weight=1)
]
else:
self._mailbox_client = None
proxy_url = f"{self._agentverse.url}/v1/proxy"
if proxy_url in [endpoint.url for endpoint in self._endpoints]:
self._agentverse.agent_type = "proxy"

self._almanac_api_url = f"{self._agentverse['http_prefix']}://{self._agentverse['base_url']}/v1/almanac"
self._almanac_api_url = f"{self._agentverse.url}/v1/almanac"
self._resolver = resolve or GlobalResolver(
max_endpoints=max_resolver_endpoints,
almanac_api_url=self._almanac_api_url,
@@ -416,6 +422,12 @@ async def _handle_get_info(_ctx: Context):
async def _handle_get_messages(_ctx: Context):
return self._message_cache

@self.on_rest_post("/prove", AgentverseUserToken, RegistrationResponse) # type: ignore
jrriehl marked this conversation as resolved.
Show resolved Hide resolved
async def _handle_prove(token: AgentverseUserToken):
return await register_in_agentverse(
token, self._identity, self._endpoints, self._agentverse
)

self._enable_agent_inspector = enable_agent_inspector

self._init_done = True
@@ -596,7 +608,7 @@ def storage(self) -> KeyValueStore:
return self._storage

@property
def mailbox(self) -> Dict[str, str]:
def mailbox(self) -> AgentverseConfig:
"""
Get the mailbox configuration of the agent.
Agentverse overrides it but mailbox is kept for backwards compatibility.
@@ -607,7 +619,7 @@ def mailbox(self) -> Dict[str, str]:
return self._agentverse

@property
def agentverse(self) -> Dict[str, str]:
def agentverse(self) -> AgentverseConfig:
"""
Get the agentverse configuration of the agent.

@@ -1027,8 +1039,7 @@ def publish_manifest(self, manifest: Dict[str, Any]):
"""
try:
resp = requests.post(
f"{self._agentverse['http_prefix']}://{self._agentverse['base_url']}"
+ "/v1/almanac/manifests",
f"{self._agentverse.url}/v1/almanac/manifests",
json=manifest,
timeout=5,
)
@@ -1183,10 +1194,7 @@ async def start_server(self):

"""
if self._enable_agent_inspector:
agentverse_url = (
f"{self._agentverse['http_prefix']}://{self._agentverse['base_url']}"
)
inspector_url = f"{agentverse_url}/inspect/"
inspector_url = f"{self._agentverse.url}/inspect/"
escaped_uri = requests.utils.quote(f"http://127.0.0.1:{self._port}")
self._logger.info(
f"Agent inspector available at {inspector_url}"
@@ -1358,7 +1366,7 @@ class Bureau:
response Futures.
_logger (Logger): The logger instance.
_server (ASGIServer): The ASGI server instance for handling requests.
_agentverse (Dict[str, str]): The agentverse configuration for the bureau.
_agentverse (AgentverseConfig): The agentverse configuration for the bureau.
_use_mailbox (bool): A flag indicating whether mailbox functionality is enabled for any
of the agents.
_registration_policy (AgentRegistrationPolicy): The registration policy for the bureau.
@@ -1408,8 +1416,10 @@ def __init__(
logger=self._logger,
)
self._agentverse = parse_agentverse_config(agentverse)
self._use_mailbox = self._agentverse["use_mailbox"]
almanac_api_url = f"{self._agentverse['http_prefix']}://{self._agentverse['base_url']}/v1/almanac"
self._use_mailbox = self._agentverse.agent_type == "mailbox"
almanac_api_url = (
f"{self._agentverse.http_prefix}://{self._agentverse.base_url}/v1/almanac"
)
almanac_contract = get_almanac_contract(test)

if wallet and seed:
@@ -1533,7 +1543,10 @@ async def run_async(self):
return
for agent in self._agents:
await agent.setup()
if agent.agentverse["use_mailbox"] and agent.mailbox_client is not None:
if (
agent.agentverse.agent_type == "mailbox"
and agent.mailbox_client is not None
):
tasks.append(agent.mailbox_client.run())
self._loop.create_task(self._schedule_registration())

2 changes: 1 addition & 1 deletion python/src/uagents/asgi.py
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@

HOST = "0.0.0.0"

RESERVED_ENDPOINTS = ["/submit", "/messages", "/agent_info"]
RESERVED_ENDPOINTS = ["/submit", "/messages", "/agent_info", "/prove"]


async def _read_asgi_body(receive):
38 changes: 28 additions & 10 deletions python/src/uagents/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from typing import Dict, List, Optional, Union
from typing import Dict, List, Literal, Optional, Union

from pydantic import BaseModel

from uagents.types import AgentEndpoint

@@ -43,6 +45,21 @@
DEFAULT_SEARCH_LIMIT = 100


AgentType = Literal["hosted", "local", "mailbox", "proxy", "custom"]

Dacksus marked this conversation as resolved.
Show resolved Hide resolved

class AgentverseConfig(BaseModel):
agent_mailbox_key: Optional[str]
Dacksus marked this conversation as resolved.
Show resolved Hide resolved
base_url: str
protocol: str
http_prefix: str
agent_type: AgentType

@property
def url(self) -> str:
return f"{self.http_prefix}://{self.base_url}"


def parse_endpoint_config(
endpoint: Optional[Union[str, List[str], Dict[str, dict]]],
) -> List[AgentEndpoint]:
@@ -72,12 +89,12 @@ def parse_endpoint_config(

def parse_agentverse_config(
config: Optional[Union[str, Dict[str, str]]] = None,
) -> Dict[str, Union[str, bool, None]]:
) -> AgentverseConfig:
"""
Parse the user-provided agentverse configuration.

Returns:
Dict[str, Union[str, bool, None]]: The parsed agentverse configuration.
AgentverseConfig: The parsed agentverse configuration.
"""
agent_mailbox_key = None
base_url = AGENTVERSE_URL
@@ -98,10 +115,11 @@ def parse_agentverse_config(
protocol, base_url = base_url.split("://")
protocol = protocol_override or protocol or "https"
http_prefix = "https" if protocol in {"wss", "https"} else "http"
return {
"agent_mailbox_key": agent_mailbox_key,
"base_url": base_url,
"protocol": protocol,
"http_prefix": http_prefix,
"use_mailbox": agent_mailbox_key is not None,
}

return AgentverseConfig(
agent_mailbox_key=agent_mailbox_key,
base_url=base_url,
protocol=protocol,
http_prefix=http_prefix,
agent_type="mailbox" if agent_mailbox_key else "custom",
)
Loading