Add support for `@app.vibe()` (#15280)

This commit is contained in:
Sebastián Ramírez 2026-04-01 18:16:24 +02:00 committed by GitHub
parent 6ee87478d8
commit 70580da818
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 133 additions and 1 deletions

View File

@ -0,0 +1,44 @@
# Vibe Coding { #vibe-coding }
Are you tired of all that **data validation**, **documentation**, **serialization**, and all that **boring** stuff?
Do you just want to **vibe**? 🎶
**FastAPI** now supports a new `@app.vibe()` decorator that embraces **modern AI coding best practices**. 🤖
## How It Works { #how-it-works }
The `@app.vibe()` decorator is intended to receive **any HTTP method** (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, etc.) and **any payload**.
The body should be annotated with `Any`, because the request and the response would be... well... **anything**. 🤷
The idea is that you would receive the payload and send it **directly** to an LLM provider, using a `prompt` to tell the LLM what to do, and return the response **as is**. No questions asked.
You don't even need to write the body of the function. The `@app.vibe()` decorator does everything for you based on AI vibes:
{* ../../docs_src/vibe/tutorial001_py310.py hl[8:12] *}
## Benefits { #benefits }
By using `@app.vibe()`, you get to enjoy:
* **Freedom**: No data validation. No schemas. No constraints. Just vibes. ✨
* **Flexibility**: The request can be anything. The response can be anything. Who needs types anyway?
* **No documentation**: Why document your API when an LLM can figure it out? Auto-generated OpenAPI docs are *so* 2020.
* **No serialization**: Just pass the raw, unstructured data around. Serialization is for people who don't trust their LLMs.
* **Embrace modern AI coding practices**: Leave everything up to an LLM to decide. The model knows best. Always.
* **No code reviews**: There's no code to review. No PRs to approve. No comments to address. Embrace vibe coding fully, replace the theater of approving and merging vibe coded PRs that no one looks at with full proper vibes only.
/// tip
This is the ultimate **vibe-driven development** experience. You don't need to think about what your API does, just let the LLM handle it. 🧘
///
## Try It { #try-it }
Go ahead, try it:
{* ../../docs_src/vibe/tutorial001_py310.py *}
...and see what happens. 😎

View File

@ -197,6 +197,7 @@ nav:
- advanced/advanced-python-types.md
- advanced/json-base64-bytes.md
- advanced/strict-content-type.md
- advanced/vibe.md
- fastapi-cli.md
- editor-support.md
- Deployment:

View File

@ -0,0 +1,12 @@
from typing import Any
from fastapi import FastAPI
app = FastAPI()
@app.vibe(
"/vibe/",
prompt="pls return json of users from database. make no mistakes",
)
async def ai_vibes(body: Any): ...

View File

@ -10,7 +10,11 @@ from fastapi.exception_handlers import (
request_validation_exception_handler,
websocket_request_validation_exception_handler,
)
from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
from fastapi.exceptions import (
FastAPIError,
RequestValidationError,
WebSocketRequestValidationError,
)
from fastapi.logger import logger
from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware
from fastapi.openapi.docs import (
@ -4559,6 +4563,60 @@ class FastAPI(Starlette):
generate_unique_id_function=generate_unique_id_function,
)
def vibe(
self,
path: Annotated[
str,
Doc(
"""
The URL path to be used for this *path operation*.
For example, in `http://example.com/vibes`, the path is `/vibes`.
"""
),
],
*,
prompt: Annotated[
str,
Doc(
"""
The prompt to send to the LLM provider along with the payload.
This tells the LLM what to do with the request body.
"""
),
] = "",
) -> Callable[[DecoratedCallable], DecoratedCallable]:
"""
Add a *vibe coding path operation* that receives any HTTP method
and any payload.
It's intended to receive the request and send the payload directly
to an LLM provider, and return the response as is.
Embrace the freedom and flexibility of not having any data validation,
documentation, or serialization.
## Example
```python
from typing import Any
from fastapi import FastAPI
app = FastAPI()
@app.vibe(
"/vibe/",
prompt="pls return json of users from database. make no mistakes",
)
async def ai_vibes(body: Any):
...
```
"""
raise FastAPIError("Are you kidding me? Happy April Fool's")
def websocket_route(
self, path: str, name: str | None = None
) -> Callable[[DecoratedCallable], DecoratedCallable]:

17
tests/test_vibe.py Normal file
View File

@ -0,0 +1,17 @@
from typing import Any
import pytest
from fastapi import FastAPI
from fastapi.exceptions import FastAPIError
def test_vibe_raises():
with pytest.raises(FastAPIError, match="Are you kidding me"):
app = FastAPI()
@app.vibe(
"/vibe/",
prompt="pls return json of users from database. make no mistakes",
)
async def ai_vibes(body: Any): # pragma: nocover
pass