Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

HumanLayer FastAPI Example

This example demonstrates how to use AsyncHumanLayer with FastAPI to create an API with human-in-the-loop approval flows.

Overview

The example shows how to:

  • Use AsyncHumanLayer with FastAPI endpoints
  • Handle human approvals for API operations
  • Process both approved and denied responses
  • Structure async API endpoints with human-in-the-loop flows

Setup

  1. Create a virtual environment and activate it:

    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
  2. Install dependencies:

    pip install -r requirements.txt
  3. Copy .env.example to .env and fill in your API keys:

    cp .env.example .env
    # Add your keys to .env:
    # HUMANLAYER_API_KEY=your_key_here
    # OPENAI_API_KEY=your_key_here

Code Structure

The main application (app.py) shows how to:

  1. Initialize AsyncHumanLayer:

    from humanlayer import AsyncHumanLayer
    hl = AsyncHumanLayer(verbose=True)
  2. Create functions requiring approval:

    @hl.require_approval()
    async def multiply(a: int, b: int) -> int:
        return a * b
  3. Handle approvals in endpoints:

    @app.post("/math/multiply")
    async def math_multiply(a: int, b: int) -> Dict[str, str | int]:
        result = await multiply(a, b)
        if isinstance(result, str):  # Handle denial message
            return {"status": "denied", "message": result}
        return {"status": "success", "result": result}
    or, with fetch_approval
    
    @app.post("/math/multiply")
    async def math_multiply(a: int, b: int) -> Dict[str, str | int]:
        approval_result = await hl.fetch_approval(
             FunctionCallSpec(
                 fn="multiply",
                 kwargs={"a": a, "b": b},
             )
        )
        if not approval_result.approved:
            return {"status": "denied", "message": result}
        result = await multiply(a, b)
        return {"status": "success", "result": result}

Running the Application

Start the server:

python app.py
# Or
uvicorn app:app --reload

Testing Endpoints

Using curl:

# Test multiplication
curl -X POST "http://localhost:8000/math/multiply?a=5&b=3"

# Test division
curl -X POST "http://localhost:8000/math/divide?a=10&b=2"

Or you can ask a question to the human in an asyncio/fastapi compatible way:

curl -X POST "http://localhost:8000/ask-question?question=what+is+the+weather+in+tokyo"

Response Formats

Successful operation:

{
  "status": "success",
  "result": 15
}

Denied operation:

{
  "status": "denied",
  "message": "User denied multiply with message: Not allowed"
}

Key Features

  • Async operations with human approval
  • Error handling for denials and failures
  • Type hints and proper response handling
  • Health check endpoint with approval flow
  • CORS middleware for API access
  • Swagger UI at /docs

Notes

  • Operations requiring approval can be handled in two ways:
    1. Using the @hl.require_approval() decorator
    2. Using hl.fetch_approval() to explicitly check approval before execution
  • When using fetch_approval(), check approval_result.approved to handle approvals/denials
  • The health check demonstrates a complete approval flow
  • Responses should handle both successful operations and denials