Skip to Content

How to add custom REST endpoints to your Agent

Introduction

uAgents now support custom REST endpoints using the on_rest_get() and on_rest_post() decorators, enabling them to handle HTTP GET and POST requests directly. With this addition, agents can define specific routes, create request and response models, and interact seamlessly with REST clients. This feature enhances the flexibility of agents, allowing them to communicate with external systems using standard web protocols while ensuring that all responses conform to predefined models. Please note that this feature is only available at the ‘agent level’, meaning that you cannot add REST endpoints to uAgents protocols!

The usage is similar to a message handler in that you define:

  • A custom endpoint in string format, e.g. "/my_rest_endpoint";
  • A Request Model (inheriting from uagents.models) for POST endpoints;
  • A Response Model for GET endpoints.

The difference to a message handler is that you actually have to invoke return for the value to be returned to the REST client. The format can either be Dict[str, Any] or the Model itself but either way the output will be validated against the predefined response model.

Usage

To use the new REST API feature in your agent, follow these steps to define custom GET and POST routes, run the Agent, and query the endpoints.

For querying the Agent you have to make sure that:

  • You use the correct REST method (“GET” or “POST”).
  • You address the Agent endpoint together with its route e.g http://localhost:8000/custom_route.

Define Custom GET and POST Routes

GET request example

Use the @on_rest_get() decorator to define a custom GET endpoint. You will need to specify the endpoint route and the response model.

@agent.on_rest_get("/custom_get_route", Response) async def handle_get(ctx: Context) -> Dict[str, Any]: return { "field": <value>, }

POST request example

Use the @on_rest_post() decorator to define a custom POST endpoint. You need to provide both a request model (for input) and a response model (for output).

@agent.on_rest_post("/custom_post_route", Request, Response) async def handle_post(ctx: Context, req: Request) -> Response: ctx.logger.info(req) return Response(...)

Example of custom GET and POST Routes

agent.py
import time from typing import Any, Dict from uagents import Agent, Context, Model class Request(Model): text: str class Response(Model): timestamp: int text: str agent_address: str # You can also use empty models to represent empty request/response bodies class EmptyMessage(Model): pass agent = Agent(name="Rest API", seed="your_seed_phrase", port=8000, endpoint=["http://localhost:8000/submit"]) @agent.on_rest_get("/rest/get", Response) async def handle_get(ctx: Context) -> Dict[str, Any]: ctx.logger.info("Received GET request") return { "timestamp": int(time.time()), "text": "Hello from the GET handler!", "agent_address": ctx.agent.address, } @agent.on_rest_post("/rest/post", Request, Response) async def handle_post(ctx: Context, req: Request) -> Response: ctx.logger.info("Received POST request") return Response( text=f"Received: {req.text}", agent_address=ctx.agent.address, timestamp=int(time.time()), ) if __name__ == "__main__": agent.run()

Run the example

  1. Run the agent: python agent.py

  2. Query the agent directly through your predefined interfaces:

    curl -d '{"text": "test"}' -H "Content-Type: application/json" -X POST http://localhost:8000/rest/post

Expected output

  • Curl Response:

    {"timestamp": 1725610956, "text": "Received: test", "agent_address": "agent1q2qavahvzm2yw237g2cq40pe8p590ppysclaffp2dd0gtk9evtxag7c8djd"}
  • Agent Logs:

    WARNING: [Rest API]: No endpoints provided. Skipping registration: Agent won't be reachable. INFO: [Rest API]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit) INFO: [Rest API]: Received POST request
Last updated on