Skip to content

Commit

Permalink
Update cross-linking
Browse files Browse the repository at this point in the history
  • Loading branch information
hinthornw committed Dec 18, 2024
1 parent f89fe49 commit 06e1e4e
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 27 deletions.
6 changes: 6 additions & 0 deletions docs/_scripts/notebook_hooks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging

Check notice on line 1 in docs/_scripts/notebook_hooks.py

View workflow job for this annotation

GitHub Actions / benchmark

Benchmark results

......................................... fanout_to_subgraph_10x: Mean +- std dev: 60.9 ms +- 1.8 ms ......................................... fanout_to_subgraph_10x_sync: Mean +- std dev: 52.3 ms +- 1.0 ms ......................................... fanout_to_subgraph_10x_checkpoint: Mean +- std dev: 73.8 ms +- 2.0 ms ......................................... fanout_to_subgraph_10x_checkpoint_sync: Mean +- std dev: 94.7 ms +- 2.0 ms ......................................... fanout_to_subgraph_100x: Mean +- std dev: 630 ms +- 30 ms ......................................... fanout_to_subgraph_100x_sync: Mean +- std dev: 511 ms +- 9 ms ......................................... fanout_to_subgraph_100x_checkpoint: Mean +- std dev: 785 ms +- 24 ms ......................................... fanout_to_subgraph_100x_checkpoint_sync: Mean +- std dev: 952 ms +- 21 ms ......................................... react_agent_10x: Mean +- std dev: 30.7 ms +- 0.6 ms ......................................... react_agent_10x_sync: Mean +- std dev: 22.9 ms +- 0.3 ms ......................................... react_agent_10x_checkpoint: Mean +- std dev: 38.0 ms +- 0.8 ms ......................................... react_agent_10x_checkpoint_sync: Mean +- std dev: 37.0 ms +- 0.5 ms ......................................... react_agent_100x: Mean +- std dev: 340 ms +- 6 ms ......................................... react_agent_100x_sync: Mean +- std dev: 274 ms +- 3 ms ......................................... react_agent_100x_checkpoint: Mean +- std dev: 854 ms +- 8 ms ......................................... react_agent_100x_checkpoint_sync: Mean +- std dev: 849 ms +- 7 ms ......................................... wide_state_25x300: Mean +- std dev: 22.8 ms +- 0.4 ms ......................................... wide_state_25x300_sync: Mean +- std dev: 14.8 ms +- 0.1 ms ......................................... wide_state_25x300_checkpoint: Mean +- std dev: 278 ms +- 14 ms ......................................... wide_state_25x300_checkpoint_sync: Mean +- std dev: 276 ms +- 14 ms ......................................... wide_state_15x600: Mean +- std dev: 26.5 ms +- 0.5 ms ......................................... wide_state_15x600_sync: Mean +- std dev: 17.2 ms +- 0.2 ms ......................................... wide_state_15x600_checkpoint: Mean +- std dev: 477 ms +- 14 ms ......................................... wide_state_15x600_checkpoint_sync: Mean +- std dev: 475 ms +- 15 ms ......................................... wide_state_9x1200: Mean +- std dev: 26.6 ms +- 0.5 ms ......................................... wide_state_9x1200_sync: Mean +- std dev: 17.2 ms +- 0.4 ms ......................................... wide_state_9x1200_checkpoint: Mean +- std dev: 311 ms +- 14 ms ......................................... wide_state_9x1200_checkpoint_sync: Mean +- std dev: 310 ms +- 15 ms

Check notice on line 1 in docs/_scripts/notebook_hooks.py

View workflow job for this annotation

GitHub Actions / benchmark

Comparison against main

+-----------------------------------------+---------+-----------------------+ | Benchmark | main | changes | +=========================================+=========+=======================+ | wide_state_9x1200_sync | 17.5 ms | 17.2 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200 | 27.1 ms | 26.6 ms: 1.02x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_9x1200_checkpoint | 316 ms | 311 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_15x600_sync | 17.3 ms | 17.2 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | wide_state_25x300 | 22.9 ms | 22.8 ms: 1.01x faster | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_sync | 274 ms | 274 ms: 1.00x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x | 339 ms | 340 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_100x_checkpoint | 849 ms | 854 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_sync | 22.7 ms | 22.9 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | react_agent_10x_checkpoint_sync | 36.6 ms | 37.0 ms: 1.01x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint_sync | 937 ms | 952 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x | 618 ms | 630 ms: 1.02x slower | +-----------------------------------------+---------+-----------------------+ | fanout_to_subgraph_100x_checkpoint | 747 ms | 785 ms: 1.05x slower | +-----------------------------------------+---------+-----------------------+ | Geometric mean | (ref) | 1.00x slower | +-----------------------------------------+---------+-----------------------+ Benchmark hidden because not significant (15): fanout_to_subgraph_10x_checkpoint, wide_state_15x600, wide_state_15x600_checkpoint_sync, wide_state_25x300_sync, fanout_to_subgraph_100x_sync, wide_state_9x1200_checkpoint_sync, react_agent_10x_checkpoint, fanout_to_subgraph_10x, react_agent_100x_checkpoint_sync, fanout_to_subgraph_10x_checkpoint_sync, fanout_to_subgraph_10x_sync, wide_state_25x300_checkpoint, react_agent_10x, wide_state_15x600_checkpoint, wide_state_25x300_checkpoint_sync
import os
from typing import Any, Dict

from mkdocs.structure.pages import Page
Expand All @@ -8,6 +9,7 @@
logger = logging.getLogger(__name__)
logging.basicConfig()
logger.setLevel(logging.INFO)
DISABLED = os.getenv("DISABLE_NOTEBOOK_CONVERT") in ("1", "true", "True")


class NotebookFile(File):
Expand All @@ -16,6 +18,8 @@ def is_documentation_page(self):


def on_files(files: Files, **kwargs: Dict[str, Any]):
if DISABLED:
return files
new_files = Files([])
for file in files:
if file.src_path.endswith(".ipynb"):
Expand All @@ -32,6 +36,8 @@ def on_files(files: Files, **kwargs: Dict[str, Any]):


def on_page_markdown(markdown: str, page: Page, **kwargs: Dict[str, Any]):
if DISABLED:
return markdown
if page.file.src_path.endswith(".ipynb"):
logger.info("Processing Jupyter notebook: %s", page.file.src_path)
body = convert_notebook(page.file.abs_src_path)
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/cloud/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The LangGraph command line interface includes commands to build and run a LangGr

[](){#langgraph.json}

## Configuration File
## Configuration File {#configuration-file}

The LangGraph CLI requires a JSON configuration file with the following keys:

Expand Down
35 changes: 18 additions & 17 deletions docs/docs/concepts/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,24 @@ A typical authentication setup involves three main components:

1. **Authentication Provider** (Identity Provider/IdP)

- A dedicated service that manages user identities and credentials
- Examples: Auth0, Supabase Auth, Okta, or your own auth server
- Handles user registration, login, password resets, etc.
- Issues tokens (JWT, session tokens, etc.) after successful authentication
* A dedicated service that manages user identities and credentials
* Handles user registration, login, password resets, etc.
* Issues tokens (JWT, session tokens, etc.) after successful authentication
* Examples: Auth0, Supabase Auth, Okta, or your own auth server

2. **LangGraph Backend** (Resource Server)

- Your LangGraph application that contains business logic and protected resources
- Validates tokens with the auth provider
- Enforces access control based on user identity and permissions
- Never stores user credentials directly
* Your LangGraph application that contains business logic and protected resources
* Validates tokens with the auth provider
* Enforces access control based on user identity and permissions
* Doesn't store user credentials directly

3. **Client Application** (Frontend)
- Web app, mobile app, or API client
- Collects user credentials and sends to auth provider
- Receives tokens from auth provider
- Includes tokens in requests to LangGraph backend

* Web app, mobile app, or API client
* Collects time-sensitive user credentials and sends to auth provider
* Receives tokens from auth provider
* Includes these tokens in requests to LangGraph backend

Here's how these components typically interact:

Expand All @@ -58,15 +59,15 @@ sequenceDiagram
LG-->>Client: 7. Return resources
```

Your `@auth.authenticate` handler in LangGraph handles steps 4-5, while your `@auth.on` handlers implement step 6.
Your [`@auth.authenticate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.authenticate) handler in LangGraph handles steps 4-5, while your [`@auth.on`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.on) handlers implement step 6.

## Authentication

Authentication in LangGraph runs as middleware on every request. Your `@auth.authenticate` handler receives request information and must:
Authentication in LangGraph runs as middleware on every request. Your [`@auth.authenticate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.authenticate) handler receives request information and should:

1. Validate the credentials
2. Return user information if valid
3. Raise an HTTP exception if invalid (or AssertionError)
3. Raise an HTTP exception or AssertionError if invalid

```python
from langgraph_sdk import Auth
Expand Down Expand Up @@ -98,12 +99,12 @@ async def authenticate(headers: dict) -> Auth.types.MinimalUserDict:

The returned user information is available:

- To your authorization handlers via `ctx.user`
- To your authorization handlers via [`ctx.user`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.AuthContext)
- In your application via `config["configuration"]["langgraph_auth_user"]`

## Authorization

After authentication, LangGraph calls your `@auth.on` handlers to control access to specific resources (e.g., threads, assistants, crons). These handlers can:
After authentication, LangGraph calls your [`@auth.on`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.on) handlers to control access to specific resources (e.g., threads, assistants, crons). These handlers can:

1. Add metadata to be saved during resource creation by mutating the `value["metadata"]` dictionary directly.
2. Filter resources by metadata during search/list or read operations by returning a [filter dictionary](#filter-operations).
Expand Down
22 changes: 14 additions & 8 deletions docs/docs/tutorials/auth/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ If everything works, the server should start and open the studio in your browser
>
> This in-memory server is designed for development and testing.
> For production use, please use LangGraph Cloud.
Now that we've seen the base LangGraph app, let's add authentication to it! In part 1, we will start with a hard-coded token for illustration purposes.
We will get to a "production-ready" authentication scheme in part 3, after mastering the basics.

Expand All @@ -49,9 +50,12 @@ VALID_TOKENS = {
"user2-token": {"id": "user2", "name": "Bob"},
}

# The "Auth" object is a container that LangGraph will use to mark our authentication function
auth = Auth()


# The `authenticate` decorator tells LangGraph to call this function as middleware
# for every request. This will determine whether the request is allowed or not
@auth.authenticate
async def get_current_user(authorization: str | None) -> Auth.types.MinimalUserDict:
"""Check if the user's token is valid."""
Expand All @@ -69,12 +73,12 @@ async def get_current_user(authorization: str | None) -> Auth.types.MinimalUserD
}
```

Notice that our authentication handler does two important things:
Notice that our [authentication](../../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.authenticate) handler does two important things:

1. Checks if a valid token is provided
2. Returns the user's identity
1. Checks if a valid token is provided in the request's [Authorization header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization)
2. Returns the user's [identity](../../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.MinimalUserDict)

Now tell LangGraph to use our authentication by adding the following to the `langgraph.json` configuration:
Now tell LangGraph to use our authentication by adding the following to the [`langgraph.json`](../../cloud/reference/cli.md#configuration-file) configuration:

```json
{
Expand Down Expand Up @@ -137,14 +141,16 @@ print(response)
```

You should see that:

1. Without a valid token, we can't access the bot
2. With a valid token, we can create threads and chat

Congratulations! You've built a chatbot that only lets "authorized" users access it. While this system doesn't (yet) implement a production-ready security scheme, we've learned the basic mechanics of how to control access to our bot. In the next tutorial, we'll learn how to give each user their own private conversations.
Congratulations! You've built a chatbot that only lets "authenticated" users access it. While this system doesn't (yet) implement a production-ready security scheme, we've learned the basic mechanics of how to control access to our bot. In the next tutorial, we'll learn how to give each user their own private conversations.

## What's Next?

Now that you can control who accesses your bot, you might want to:
1. Move on to [Resource Authorization](resource_auth.md) to learn how to make conversations private
2. Read more about [authentication concepts](../../concepts/auth.md)
3. Check out the [API reference](../../cloud/reference/sdk/python_sdk_ref.md) for more authentication options

1. Continue the tutorial by going to [Making Conversations Private (Part 2/3)](resource_auth.md) to learn about resource authorization.
2. Read more about [authentication concepts](../../concepts/auth.md).
3. Check out the [API reference](../../cloud/reference/sdk/python_sdk_ref.md) for more authentication details.
10 changes: 9 additions & 1 deletion libs/sdk-py/langgraph_sdk/auth/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,20 @@ def identity(self) -> str:


class MinimalUserDict(typing.TypedDict, total=False):
"""The minimal user dictionary."""
"""The dictionary representation of a user."""

identity: typing_extensions.Required[str]
"""The required unique identifier for the user."""
display_name: str
"""The optional display name for the user."""
is_authenticated: bool
"""Whether the user is authenticated. Defaults to True."""
permissions: Sequence[str]
"""A list of permissions associated with the user.
You can use these in your `@auth.on` authorization logic to determine
access permissions to different resources.
"""


@typing.runtime_checkable
Expand Down

0 comments on commit 06e1e4e

Please sign in to comment.