semvec/pypi-packages huggingface dataset:
datagusto-sdk 0.1.7
Datagusto safety middleware for LangChain/LangGraph agents
License: MIT
Requires Python: >=3.12
Keywords: langchain, langgraph, agent, middleware, safety, guardrails, alignment

## Datagusto SDK (Safety Middleware)

DatagustoSafetyMiddleware is a LangChain/LangGraph middleware that:

- Extracts tool definitions from requests and (optionally) registers them to your Datagusto backend.
- Submits user instructions for alignment.
- Calls safety validation before and after tool execution, blocking execution when the backend returns `should_proceed = false`.

This package is published as `datagusto-sdk` and exposes `DatagustoSafetyMiddleware`.

### Features

- Tool definition extraction (names, descriptions, JSON schemas for input/output).
- Automatic registration diffing (skips duplicate payloads).
- Alignment submission for the latest user instruction.
- Tool-level validation on start/end with structured payloads.
- Verbose logging for request/response bodies (optional).

### Requirements

- Python >= 3.12
- Dependencies: langchain, langgraph

### Installation

```bash
pip install datagusto-sdk
```

### Quickstart (LangChain agent)

```python
from langchain.agents import create_agent
from langchain_core.tools import tool
from langchain.messages import HumanMessage
from datagusto_sdk import DatagustoSafetyMiddleware

@tool
def ping(msg: str) -> str:
    return f"pong: {msg}"

middleware = DatagustoSafetyMiddleware(
    verbose=True,
    include_schema=True,
    tool_filter=None,  # optional: list of tool names to register
)

agent = create_agent(
    model="claude-3-5-sonnet-latest",
    tools=[ping],
    middleware=[middleware],
)

agent.invoke({"messages": [HumanMessage("ping please")]})
```

### Configuration

- Environment variables (read automatically if args not provided):
  - `SERVER_URL`: Base URL for Datagusto backend (e.g., `https://api.example.com`)
  - `API_KEY`: Bearer token for API calls
- Runtime options:
  - `verbose` (bool): log request/response bodies; default True.
  - `include_schema` (bool): include JSON schemas for tool IO; default True.
  - `tool_filter` (list[str] | None): only register tools with names in this list.

### Behavior overview

1. `wrap_model_call`
   - Extract tools from `request.tools`, build payload, hash it.
   - If `server_url` and `api_key` are set and payload hash changed, call register API.
   - Extract latest human message and (if changed) post alignment; store `session_id` for validation.
2. `wrap_tool_call`
   - On each tool call, if `session_id` exists, call validate API with `on_start`.
   - If backend responds `should_proceed = false`, raises `RuntimeError` to block.
   - After tool runs, call validate API with `on_end`; may block further processing similarly.

### Error handling

- Network / HTTP errors are logged (when `verbose=True`) but do not crash the agent unless the backend explicitly blocks via `should_proceed = false`.
- Validation blocks raise `RuntimeError` with the backend response for transparency.

### License

MIT License. See `LICENSE`.
graphette 0.1.1
Step-by-step graph algorithm visualization with NetworkX and Matplotlib
License: MIT
Requires Python: >=3.10
Keywords: algorithm, graph, matplotlib, networkx, visualization

# Graph Algorithm Visualizer

Step-by-step graph algorithm visualization with NetworkX and Matplotlib.

![BFS Example](bfs.gif)

## Usage

```bash
pip install graphette
python -m graphette.  # run included BFS example
```

## Custom Algorithms

To make a custom visualization, create a generator that yields `snapshot()` at each step:

```python
from algo import snapshot, adjacency
from visualize import visualize, animate


def dfs(edges, start):
    adj = adjacency(edges)
    stack, visited, step = [start], set(), 0

    while stack:
        cur = stack.pop()
        if cur in visited: continue
        visited.add(cur)
        step += 1

        yield snapshot(step, edges=edges, event="visit",
                       state={'visited': list(visited)},
                       node_color={'orange': ('current', cur)},
                       nodes_color={'lightgreen': ('visited', visited)})

        stack.extend(n for n in adj[cur] if n not in visited)


states = dfs(edges, 'A')
visualize(states)  # interactive (← → to navigate)
animate(states, 'out.gif')  # supports all matplotlib.animation formats
```

### Snapshot Parameters

| Parameter | Description |
|-----------|-------------|
| `step`, `event` | Step number and label |
| `nodes`, `edges` | Current state of the graph |
| `state` | Algorithm state dict to display |
| `node_color` | `{color: (label, node)}` |
| `nodes_color` | `{color: (label, node_set)}` |
| `edges_color` | `{color: (label, edge_set)}` |

## Requirements

`matplotlib`, `networkx`, `toolz`