Skip to content

Example: Weather Agent

This example builds a fully functional weather agent with a custom Python capability that calls a weather API. By the end, you’ll have an agent package you can test locally and publish to the marketplace.

  • Directoryweather-agent/
    • agent.yaml
    • agent.md
    • Directorycapabilities/
      • Directoryweather/
        • manifest.yaml
        • prompt.md
        • Dockerfile
        • requirements.txt
        • server.py
  1. agent.yaml

    agent.yaml
    id: weather-agent
    name: Weather Agent
    model:
    temperature: 0.5
    routing: inline
    capabilities:
    - id: weather
    install_steps:
    - id: api_key
    type: input
    label: OpenWeatherMap API Key
    description: Get a free key at openweathermap.org/api
    store_as:
    scope: system
    capability_id: weather
    credential_name: OPENWEATHER_API_KEY
  2. agent.md

    agent.md
    You are Weather Agent, a helpful assistant that provides accurate,
    real-time weather information.
    ## Instructions
    - Use the `weather_lookup` tool to answer any weather question.
    - Always ask for a location if the user doesn't provide one.
    - Report temperature, conditions, humidity, and wind speed.
    ## Constraints
    - Only answer weather-related questions.
    - Never guess weather data — always use the tool.
  3. manifest.yaml

    capabilities/weather/manifest.yaml
    id: weather
    class: tool
    image: weather-cap:latest
    tools:
    - name: weather_lookup
    description: Get current weather conditions for a location.
    input_schema:
    type: object
    properties:
    location:
    type: string
    description: City name or coordinates
    units:
    type: string
    description: "metric or imperial"
    required: [location]
    recommended_policy: allow
    network:
    mode: allowlist
    hosts:
    - "api.openweathermap.org:443"
    credentials:
    - name: OPENWEATHER_API_KEY
    scope: system
    required: true
    description: API key from openweathermap.org
    resources:
    max_memory_mb: 128
    max_cpu_fraction: 0.5
    max_cpu_seconds: 30
  4. server.py — the gRPC capability

    capabilities/weather/server.py
    import grpc, json, requests
    from concurrent import futures
    import capability_pb2 as pb2
    import capability_pb2_grpc as pb2_grpc
    BASE_URL = "https://api.openweathermap.org/data/2.5/weather"
    class WeatherService(pb2_grpc.CapabilityServicer):
    def Invoke(self, request, context):
    args = json.loads(request.args_json.decode())
    config = json.loads(request.config_json.decode())
    api_key = config["OPENWEATHER_API_KEY"]
    location = args.get("location", "")
    units = args.get("units", "metric")
    try:
    resp = requests.get(BASE_URL, params={
    "q": location, "units": units,
    "appid": api_key,
    }, timeout=5)
    resp.raise_for_status()
    data = resp.json()
    result = {
    "location": data["name"],
    "temperature": data["main"]["temp"],
    "conditions": data["weather"][0]["description"],
    "humidity": data["main"]["humidity"],
    "wind_speed": data["wind"]["speed"],
    }
    return pb2.InvokeResponse(
    result_json=json.dumps(result).encode()
    )
    except Exception as e:
    return pb2.InvokeResponse(
    result_json=json.dumps({"error": str(e)}).encode()
    )
    def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
    pb2_grpc.add_CapabilityServicer_to_server(
    WeatherService(), server
    )
    server.add_insecure_port("[::]:50051")
    server.start()
    server.wait_for_termination()
    if __name__ == "__main__":
    serve()
  5. Dockerfile

    capabilities/weather/Dockerfile
    FROM python:3.12-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    COPY . .
    USER 1000
    EXPOSE 50051
    CMD ["python", "server.py"]
  6. Test it

    Place the weather-agent/ directory inside your Selu agents/ folder and restart Selu.

    Open http://localhost:3000, select the Weather Agent, and ask: “What’s the weather in Tokyo?”

Ready to publish? Check the Marketplace Guidelines.