Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Archento committed Nov 19, 2024
1 parent f1fcfe3 commit 6730c3e
Show file tree
Hide file tree
Showing 6 changed files with 371 additions and 31 deletions.
71 changes: 56 additions & 15 deletions python/docs/api/uagents/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,21 @@ Get the balance of the agent.
- `int` - Bank balance.
<a id="src.uagents.agent.Agent.info"></a>
#### info
```python
@property
def info() -> AgentInfo
```
Get basic information about the agent.
**Returns**:
- `AgentInfo` - The agent's address, endpoints, protocols, and metadata.
<a id="src.uagents.agent.Agent.metadata"></a>
#### metadata
Expand Down Expand Up @@ -478,18 +493,26 @@ Sign the provided digest.
#### sign`_`registration
```python
def sign_registration() -> str
def sign_registration(timestamp: int,
sender_wallet_address: Optional[str] = None) -> str
```
Sign the registration data for Almanac contract.
**Arguments**:
- `timestamp` _int_ - The timestamp for the registration.
- `sender_wallet_address` _Optional[str]_ - The wallet address of the transaction sender.
**Returns**:
- `str` - The signature of the registration data.
**Raises**:
- `AssertionError` - If the Almanac contract address is None.
- `AssertionError` - If the Almanac contract is None.
<a id="src.uagents.agent.Agent.update_endpoints"></a>
Expand Down Expand Up @@ -736,6 +759,16 @@ async def setup()
Include the internal agent protocol, run startup tasks, and start background tasks.
<a id="src.uagents.agent.Agent.start_registration_loop"></a>
#### start`_`registration`_`loop
```python
def start_registration_loop()
```
Start the registration loop.
<a id="src.uagents.agent.Agent.start_message_dispenser"></a>
#### start`_`message`_`dispenser
Expand Down Expand Up @@ -794,7 +827,8 @@ Create all tasks for the agent.
def run()
```
Run the agent.
Run the agent by itself.
A fresh event loop is created for the agent and it is closed after the agent stops.
<a id="src.uagents.agent.Agent.get_message_protocol"></a>
Expand All @@ -819,27 +853,20 @@ A class representing a Bureau of agents.
This class manages a collection of agents and orchestrates their execution.
**Arguments**:
- `agents` _Optional[List[Agent]]_ - The list of agents to be managed by the bureau.
- `port` _Optional[int]_ - The port number for the server.
- `endpoint` _Optional[Union[str, List[str], Dict[str, dict]]]_ - Configuration
for agent endpoints.
**Attributes**:
- `_loop` _asyncio.AbstractEventLoop_ - The event loop.
- `_agents` _List[Agent]_ - The list of agents to be managed by the bureau.
- `_registered_agents` _List[Agent]_ - The list of agents contained in the bureau.
- `_endpoints` _List[Dict[str, Any]]_ - The endpoint configuration for the bureau.
- `_port` _int_ - The port on which the bureau's server runs.
- `_queries` _Dict[str, asyncio.Future]_ - Dictionary mapping query senders to their
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.
- `_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.
<a id="src.uagents.agent.Bureau.__init__"></a>
Expand All @@ -849,6 +876,12 @@ This class manages a collection of agents and orchestrates their execution.
def __init__(agents: Optional[List[Agent]] = None,
port: Optional[int] = None,
endpoint: Optional[Union[str, List[str], Dict[str, dict]]] = None,
agentverse: Optional[Union[str, Dict[str, str]]] = None,
registration_policy: Optional[BatchRegistrationPolicy] = None,
ledger: Optional[LedgerClient] = None,
wallet: Optional[LocalWallet] = None,
seed: Optional[str] = None,
test: bool = True,
loop: Optional[asyncio.AbstractEventLoop] = None,
log_level: Union[int, str] = logging.INFO)
```
Expand All @@ -857,9 +890,17 @@ Initialize a Bureau instance.
**Arguments**:
- `port` _Optional[int]_ - The port on which the bureau's server will run.
- `endpoint` _Optional[Union[str, List[str], Dict[str, dict]]]_ - The endpoint configuration
for the bureau.
- `agents` _Optional[List[Agent]]_ - The list of agents to be managed by the bureau.
- `port` _Optional[int]_ - The port number for the server.
- `endpoint` _Optional[Union[str, List[str], Dict[str, dict]]]_ - The endpoint configuration.
- `agentverse` _Optional[Union[str, Dict[str, str]]]_ - The agentverse configuration.
- `registration_policy` _Optional[BatchRegistrationPolicy]_ - The registration policy.
- `ledger` _Optional[LedgerClient]_ - The ledger for the bureau.
- `wallet` _Optional[LocalWallet]_ - The wallet for the bureau (overrides 'seed').
- `seed` _Optional[str]_ - The seed phrase for the wallet (overridden by 'wallet').
- `test` _Optional[bool]_ - True if the bureau will register and transact on the testnet.
- `loop` _Optional[asyncio.AbstractEventLoop]_ - The event loop.
- `log_level` _Union[int, str]_ - The logging level for the bureau.
<a id="src.uagents.agent.Bureau.add"></a>
Expand Down
3 changes: 2 additions & 1 deletion python/docs/api/uagents/crypto/__init__.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ Sign the provided digest.
#### sign`_`registration

```python
def sign_registration(contract_address: str, sequence: int) -> str
def sign_registration(contract_address: str, timestamp: int,
wallet_address: str) -> str
```

Sign the registration data for the Almanac contract.
Expand Down
179 changes: 179 additions & 0 deletions python/docs/api/uagents/experimental/quota/__init__.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<a id="src.uagents.experimental.quota.__init__"></a>

# src.uagents.experimental.quota.`__`init`__`

This Protocol class can be used to rate limit `on_message` message handlers.

The rate limiter uses the agents storage to keep track of the number of requests
made by another agent within a given time window. If the number of requests exceeds
a specified limit, the rate limiter will block further requests until the time
window resets.

> Default: Not rate limited, but you can set a default during initialization.
Additionally, the protocol can be used to set access control rules for handlers
allowing or blocking specific agents from accessing the handler.
The default access control rule can be set to allow or block all agents.

Both rules can work together to provide a secure and rate-limited environment for
message handlers.


Usage examples:

```python
from uagents.experimental.quota import AccessControlList, QuotaProtocol, RateLimit

# Initialize the QuotaProtocol instance
quota_protocol = QuotaProtocol(
storage_reference=agent.storage,
name="quota_proto",
version=agent._version,
# default_rate_limit=RateLimit(window_size_minutes=1, max_requests=3), # Optional
)

# This message handler is not rate limited
@quota_protocol.on_message(ExampleMessage1)
async def handle(ctx: Context, sender: str, msg: ExampleMessage1):
...

# This message handler is rate limited with custom window size and request limit
@quota_protocol.on_message(
ExampleMessage2,
rate_limit=RateLimit(window_size_minutes=1, max_requests=3),
)
async def handle(ctx: Context, sender: str, msg: ExampleMessage2):
...

# This message handler has access control rules set
@quota_protocol.on_message(
ExampleMessage3,
acl=AccessControlList(default=False, allowed={"<agent_address>"}),
)
async def handle(ctx: Context, sender: str, msg: ExampleMessage3):
...

agent.include(quota_protocol)
```

Tip: The `AccessControlList` object can be used to set access control rules during
runtime. This can be useful for dynamic access control rules based on the state of the
agent or the network.
```python
acl = AccessControlList(default=True)

@proto.on_message(model=Message, access_control_list=acl)
async def message_handler(ctx: Context, sender: str, msg: Message):
if REASON_TO_BLOCK:
acl.blocked.add(sender)
ctx.logger.info(f"Received message from {sender}: {msg.text}")
```

<a id="src.uagents.experimental.quota.__init__.QuotaProtocol"></a>

## QuotaProtocol Objects

```python
class QuotaProtocol(Protocol)
```

<a id="src.uagents.experimental.quota.__init__.QuotaProtocol.__init__"></a>

#### `__`init`__`

```python
def __init__(storage_reference: StorageAPI,
name: Optional[str] = None,
version: Optional[str] = None,
default_rate_limit: Optional[RateLimit] = None,
default_acl: Optional[AccessControlList] = None)
```

Initialize a QuotaProtocol instance.

**Arguments**:

- `storage_reference` _StorageAPI_ - The storage reference to use for rate limiting.
- `name` _Optional[str], optional_ - The name of the protocol. Defaults to None.
- `version` _Optional[str], optional_ - The version of the protocol. Defaults to None.
- `default_rate_limit` _Optional[RateLimit], optional_ - The default rate limit.
Defaults to None.
- `default_acl` _Optional[AccessControlList], optional_ - The access control list.
Defaults to None.

<a id="src.uagents.experimental.quota.__init__.QuotaProtocol.on_message"></a>

#### on`_`message

```python
def on_message(model: Type[Model],
replies: Optional[Union[Type[Model], Set[Type[Model]]]] = None,
allow_unverified: Optional[bool] = False,
rate_limit: Optional[RateLimit] = None,
access_control_list: Optional[AccessControlList] = None)
```

Overwritten decorator to register a message handler for the protocol
including rate limiting.

**Arguments**:

- `model` _Type[Model]_ - The message model type.
- `replies` _Optional[Union[Type[Model], Set[Type[Model]]]], optional_ - The associated
reply types. Defaults to None.
- `allow_unverified` _Optional[bool], optional_ - Whether to allow unverified messages.
Defaults to False.
- `rate_limit` _Optional[RateLimit], optional_ - The rate limit to apply. Defaults to None.
- `access_control_list` _Optional[AccessControlList], optional_ - The access control list to
apply.


**Returns**:

- `Callable` - The decorator to register the message handler.

<a id="src.uagents.experimental.quota.__init__.QuotaProtocol.wrap"></a>

#### wrap

```python
def wrap(func: MessageCallback,
rate_limit: Optional[RateLimit] = None,
acl: Optional[AccessControlList] = None) -> MessageCallback
```

Decorator to wrap a function with rate limiting.

**Arguments**:

- `func` - The function to wrap with rate limiting
- `rate_limit` - The rate limit to apply
- `acl` - The access control list to apply


**Returns**:

- `Callable` - The decorated

<a id="src.uagents.experimental.quota.__init__.QuotaProtocol.add_request"></a>

#### add`_`request

```python
def add_request(agent_address: str, function_name: str,
window_size_minutes: int, max_requests: int) -> bool
```

Add a request to the rate limiter if the current time is still within the
time window since the beginning of the most recent time window. Otherwise,
reset the time window and add the request.

**Arguments**:

- `agent_address` - The address of the agent making the request


**Returns**:

False if the maximum number of requests has been exceeded, True otherwise

Loading

0 comments on commit 6730c3e

Please sign in to comment.