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): add experimental rate limiter agent and protocol #562

Merged
merged 7 commits into from
Oct 21, 2024

Conversation

Archento
Copy link
Member

@Archento Archento commented Oct 17, 2024

Proposed Changes

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:

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.

acl = AccessControlList(default=True, allowed={""}, blocked={""})

@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}")

Types of changes

  • Bug fix (non-breaking change that fixes an issue).
  • New feature added (non-breaking change that adds functionality).
  • Breaking change (fix or feature that would cause existing functionality to stop working as expected).
  • Documentation update.
  • Something else (e.g., tests, scripts, example, deployment, infrastructure).

Checklist

  • I have read the CONTRIBUTING guide
  • Checks and tests pass locally

If applicable

  • I have added tests that prove my fix is effective or that my feature works
  • I have checked that code coverage does not decrease
  • I have added/updated the documentation

Copy link
Contributor

@jrriehl jrriehl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! 🌟

@Archento Archento merged commit 8cf6b90 into main Oct 21, 2024
9 checks passed
@Archento Archento deleted the feat/rate-limited-message-handlers branch October 21, 2024 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants