Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 183 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,223 @@
![Genkit logo](docs/resources/genkit-logo-dark.png#gh-dark-mode-only 'Genkit')
![Genkit logo](docs/resources/genkit-logo.png#gh-light-mode-only 'Genkit')

# Genkit Python SDK

Build powerful agentic apps with Genkit Python. Genkit is Google's open-source framework for building full-stack, AI-powered and agentic applications.
Build production-ready AI applications in Python with type-safe flows, structured outputs, and integrated observability.

## Quick Start
[Documentation](https://genkit.dev/docs/python/get-started/) | [Samples](samples/) | [Discord](https://discord.gg/qXt5zzQKpc) | [Report Issue](https://github.com/genkit-ai/genkit-python/issues)

Get started in three simple steps:
---

1. **Install the SDK and your preferred model provider:**
```bash
uv add genkit genkit-google-genai
```
## Quick Start & Core Patterns

Install the SDK and model provider:

2. **Set your API key:**
```bash
uv add genkit genkit-google-genai genkit-google-cloud genkit-middleware
export GEMINI_API_KEY="your-api-key"
```

3. **Create your AI application:**
### 1. Streaming Generation

```python
from genkit import Genkit
from genkit_google_genai import GoogleAI

# 1. Initialize Genkit with the Google AI (Gemini) plugin
ai = Genkit(plugins=[GoogleAI()])

# 2. Define a type-safe tool
@ai.tool(description="Get current weather for a city")
def get_weather(city: str) -> str:
return f"Sunny, 72°F in {city}"

# 3. Define an observable flow
@ai.flow()
async def plan_trip(destination: str) -> str:
response = await ai.generate(
model="googleai/gemini-flash-latest",
prompt=f"Suggest activities in {destination} given the weather.",
tools=[get_weather],
)
return response.text # => "Based on the sunny weather in Seattle..."
# Stream text responses in real-time
stream = ai.generate_stream(
model="googleai/gemini-flash-latest",
prompt="Stream a 2-line poem about space.",
)
async for chunk in stream:
print(chunk.text, end="")

# Access final response metadata
response = await stream.response
```

## Why Genkit?
### 2. Streaming Tool Calling & Structured Output

- **Type-Safe by Design:** Leverage Python type annotations and Pydantic models for structured inputs, outputs, and tool definitions.
- **Multi-Model Provider API:** Switch effortlessly between Google Gemini, Anthropic Claude, OpenAI, Ollama, and Vertex AI with a unified API.
- **Integrated Observability:** Built-in OpenTelemetry tracing and evaluation metrics. Inspect spans and debug flows in real-time using the Genkit Developer UI (`genkit start`).
- **Deploy Anywhere:** Expose flows as standard ASGI/WSGI applications compatible with FastAPI, Flask, Django, Cloud Run, or any serverless platform.
```python
from pydantic import BaseModel, Field
from genkit import Genkit
from genkit_google_genai import GoogleAI

---
ai = Genkit(plugins=[GoogleAI()])

## Repository & Development Guidelines
# Define a tool with Pydantic type annotations
class WeatherInput(BaseModel):
city: str = Field(description="Target city name")

@ai.tool(description="Get current weather for a location")
async def get_weather(input: WeatherInput) -> str:
return f"Sunny, 72°F in {input.city}"

# Define structured output schema
class ActivityPlan(BaseModel):
activities: list[str]
outfit: str

# Stream response with automatic tool execution and structured output
stream = ai.generate_stream(
model="googleai/gemini-flash-latest",
prompt="Suggest activities for Seattle today.",
tools=[get_weather],
output_schema=ActivityPlan,
)
async for chunk in stream:
if chunk.text:
print(chunk.text, end="")

# Access validated Pydantic output object
response = await stream.response
print(response.output)
# => ActivityPlan(activities=['Kayak on Lake Union', 'Discovery Park'], outfit='Light jacket')
```

### 3. Tool Approval Middleware & Restarts

This section covers onboarding and common development workflows for contributing to the Genkit Python SDK.
```python
from genkit import Genkit
from genkit_google_genai import GoogleAI
from genkit_middleware import Middleware, ToolApproval

ai = Genkit(plugins=[GoogleAI(), Middleware()])
tool_approval = ToolApproval(allowed_tools=[])

@ai.tool(description="Transfer money to an account")
async def transfer_money(amount: float, to_account: str) -> str:
return f"Transferred ${amount} to {to_account}"

agent = ai.define_agent(
name="bankingAgent",
model="googleai/gemini-flash-latest",
system="Banking assistant. Call transfer_money when requested.",
tools=[transfer_money],
use=[tool_approval],
)

chat = agent.chat()
out1 = await chat.send("Transfer $100 to account 999.")
# => Returns INTERRUPTED status because transfer_money requires approval

# Approve pending tool interrupts and resume execution
restarts = [intr.restart(resumed_metadata={"tool_approved": True}) for intr in out1.interrupts]
out2 = await chat.resume(restart=restarts)
print(out2.text)
# => "$100 has been successfully transferred to account 999."
```

### Prerequisites
- **Python 3.10+**
- **[uv](https://docs.astral.sh/uv/getting-started/installation/):** Fast Python package and project manager (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
- **[just](https://github.com/casey/just#installation):** Modern command runner (`brew install just` or `cargo install just`)
### 4. Agent Loops & Persistent Sessions

### Workspace Structure
```python
from genkit import Genkit
from genkit_google_cloud import FirestoreSessionStore
from genkit_google_genai import GoogleAI

ai = Genkit(plugins=[GoogleAI()])

# Persist multi-turn session history in Cloud Firestore
store = FirestoreSessionStore()

# Define an agent with persistent session memory
agent = ai.define_agent(
name="supportAgent",
model="googleai/gemini-flash-latest",
system="You are a helpful customer support agent.",
store=store,
)

# Multi-turn chat with automatic persistent session state
chat = agent.chat()
res1 = await chat.send("Hi, my name is Alex.")
res2 = await chat.send("What was my name again?")
print(res2.text)
# => "Your name is Alex!"
```
py/
├── bin/ # CI/CD and release automation scripts
├── docs/ # Playbooks and generated API reference templates
├── packages/ # Core framework and official integrations
├── samples/ # Runnable example applications and demos
├── scripts/ # Maintenance and verification scripts
├── tests/ # Cross-package integration test suites
├── justfile # Command runner shortcuts (just py <command>)
├── noxfile.py # Multi-version test automation (3.10–3.14)
├── pyproject.toml # Workspace metadata and tool dependencies
└── uv.lock # Resolved dependency lockfile

---

## Key Capabilities

<table>
<tr>
<td><strong>Type-Safe by Design</strong></td>
<td>Leverage native Python type annotations and Pydantic models for structured inputs, outputs, and automatic tool schema generation.</td>
</tr>
<tr>
<td><strong>Unified Model API</strong></td>
<td>Switch effortlessly between Google Gemini, Anthropic Claude, OpenAI, Ollama, and Vertex AI using a single consistent interface.</td>
</tr>
<tr>
<td><strong>Integrated Observability</strong></td>
<td>Built-in OpenTelemetry tracing. Inspect execution graphs, token usage, latency, and step inputs/outputs locally in real-time.</td>
</tr>
<tr>
<td><strong>Production Deployment</strong></td>
<td>Expose flows as standard ASGI/WSGI applications compatible with FastAPI, Flask, Django, Cloud Run, or any serverless platform.</td>
</tr>
</table>

---

## Developer Tools & Dev UI

Accelerate AI development with the local Genkit Developer UI and CLI.

```bash
genkit start -- uv run main.py
```

### Development Commands (`just py`)
Key features:
- **Playground**: Run and experiment with Genkit flows, prompts, and tools in dedicated playgrounds.
- **Trace Inspector**: Analyze detailed execution traces, including step-by-step breakdowns of complex flows.
- **Evaluations**: Review performance metrics and evaluate model outputs over time.

<img src="docs/resources/readme-ui-traces-screenshot.png" width="700" alt="Screenshot of Genkit Developer UI showing traces">

From the repository root, run `just py <command>` (or `just <command>` in `py/`):
---

## Exploring Samples & Onboarding

Browse runnable, real-world applications in [`samples/`](samples/):

- **`sync`** — Install workspace dependencies (`uv sync`).
- **`lint`** — Run formatters, linters, and type checkers (maps to CI `lint-and-format` / `type-check`).
- **`fmt`** — Auto-format code and fix lint errors.
- **`test`** — Run unit tests (use `test-nox` to test Python 3.10–3.14 like CI).
- **`check`** — Validate workspace version consistency.
- **[Basic Flows](samples/basic-flows)**: Text generation, structured output, and tool calling
- **[Model Providers](samples/)**: Integrations for Gemini, Anthropic, OpenAI, Ollama, and Vertex AI
- **[Agentic Workflows](samples/agents)**: Multi-turn agents, session memory, and approval interrupts
- **[Web Frameworks](samples/)**: Integrations with FastAPI, Flask, and Django

### Running Samples
### Running Samples Locally

To run example applications from `samples/`, navigate to a sample directory and launch the Genkit Developer UI:
Clone the repository and launch any sample with the interactive Dev UI:

```bash
cd samples/<sample-name>
genkit start -- uv run <entrypoint.py>
genkit start -- uv run main.py
```

Open the Dev UI in your browser to interact with registered flows and agents directly.
---

## Local Development

If you're contributing to the Python SDK:

1. **Prerequisites**: Python 3.10+ and [`uv`](https://docs.astral.sh/uv/) (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
2. **Install Dependencies**: `uv sync`
3. **Run Linters & Tests**: `just lint` and `just test`

For coding standards and detailed guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).

---

## Connect with Us

### Documentation & Maintenance
- **API Reference:** For complete class and method signatures, see [docs/index.md](docs/index.md).
- **Contributing & Standards:** For coding conventions, commit guidelines, and type-checking rules, see [CONTRIBUTING.md](../CONTRIBUTING.md).
- **Release Playbook:** For maintainer release procedures, see [docs/release_playbook.md](docs/release_playbook.md).
- [**Follow us on X/Twitter**](https://x.com/GenkitFramework) – News, updates, and tips.
- [**Join us on Reddit**](https://reddit.com/r/GenkitFramework) – Community discussion and Q&A.
- [**Join us on Discord**](https://discord.gg/qXt5zzQKpc) – Get real-time help and chat with developers.
- [**Contribute on GitHub**](https://github.com/genkit-ai/genkit-python/issues) – Report bugs, suggest features, or submit PRs.

## License
Apache 2.0
Binary file added docs/resources/genkit-logo-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/resources/genkit-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/resources/readme-ui-traces-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/genkit/tests/genkit/ai/generate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2259,6 +2259,8 @@ async def injected_tool() -> str:

specs = []
spec_path = pathlib.Path(__file__).parent / '../../../../../../tests/specs/generate.yaml'
if not spec_path.resolve().exists():
spec_path = pathlib.Path(__file__).parent / '../../../../../tests/specs/generate.yaml'
with spec_path.resolve().open() as stream:
tests_spec = yaml.safe_load(stream)
specs = tests_spec['tests']
Expand Down
Loading
Loading