Ctrl K
ComunidadGuías…

docs/quickstart.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Quickstart

In about five minutes: install toolpass, ask it a question, put it in front of an agent tool, then
run the same thing as a server. You need Python 3.10 or later; step 3 also uses Docker (or
nothing more than the same `pip install`) and, for the Node client, Node 18.17 or later. Nothing
here touches a real system; step 4 connects one.

## 1. Install and ask

```sh
python3 -m venv .venv && . .venv/bin/activate
pip install toolpass
curl -sO https://raw.githubusercontent.com/roee-hersh/toolpass/main/examples/toolpass.yaml
```

The example config has a `demo` connection that talks to nothing. In it, `admin@example.com` may
write and `dana@example.com` may not. The engine runs in your process:

```sh
python3 -c '
from toolpass import Toolpass
tp = Toolpass.from_config("toolpass.yaml")
print(tp.check("dana@example.com", "demo", "thing.write", "thing:1"))
'
```

```text
Decision(decision='deny', reason='denied: dana@example.com is not an admin', status=200, identity='dana@example.com')
```

Change the user to `admin@example.com` and the answer is `allow`. Try `nobody@example.com` and it is
`deny` with `user_not_found`. Every answer is also a JSON line on stderr: that is the
[decision log](guides/operating.md#decision-log), set by `decision_log` in the file.

The command line asks the same question without any code:

```sh
toolpass check -config toolpass.yaml -connection demo \
  -user dana@example.com -action thing.write -resource thing:1
```

## 2. Guard a tool

Wrap the function your agent calls, so it runs only after toolpass said `allow`. The user comes from
your application, never from the model. Save as `quickstart.py`:

```python
from contextvars import ContextVar
from toolpass import Toolpass, PermissionDenied, guarded

tp = Toolpass.from_config("toolpass.yaml")
current_user: ContextVar[str] = ContextVar("current_user")

@guarded(tp, "demo", "thing.write", "thing:{thing_id}", user=current_user)
def write_thing(thing_id: str) -> str:
    return f"wrote thing {thing_id}"  # your real action goes here

for who in ["admin@example.com", "dana@example.com"]:
    current_user.set(who)  # in a real agent: the signed-in user, never the model
    try:
        print(who, "->", write_thing(thing_id="1"))
    except PermissionDenied as e:
        print(who, "-> refused:", e.decision.reason)
```

```sh
python3 quickstart.py 2>/dev/null   # stderr carries the decision log
```

```text
admin@example.com -> wrote thing 1
dana@example.com -> refused: denied: dana@example.com is not an admin
```

In a real agent, use your framework's adapter instead, configured once on the agent
(`toolpass.strands`, `toolpass.langchain`, ...), or put the framework's tool
decorator on top of `guarded`. The [agent guide](guides/agent-tools.md) covers each framework and
where the user comes from.

## 3. Run it as a server

In-process, the agent's process holds toolpass's lookup credentials. To keep them out of it, run
the same engine as a service and point the agent at it:

```sh
docker run --rm -p 8080:8080 -e TOOLPASS_API_KEY=change-me \
  -v "$PWD/toolpass.yaml:/etc/toolpass/toolpass.yaml:ro" ghcr.io/roee-hersh/toolpass
```

No Docker? The package you installed is the server too:
`TOOLPASS_API_KEY=change-me toolpass serve -config toolpass.yaml`.

In a second terminal:

```sh
curl -X POST localhost:8080/check -H 'Authorization: Bearer change-me' \
  -d '{"user":"dana@example.com","connection":"demo","action":"thing.write","resource":"thing:1"}'
```

```json
{"decision":"deny","reason":"denied: dana@example.com is not an admin"}
```

In `quickstart.py`, change one line and run it again; the output is the same:

```python
tp = Toolpass.remote("http://localhost:8080", "change-me")  # or TOOLPASS_URL and TOOLPASS_API_KEY
```

**Node** talks to the server with `toolpass-client`. Save as `quickstart.mjs` (the `.mjs`
extension lets it use `import`):

```sh
npm install toolpass-client
```

```js
import { AsyncLocalStorage } from "node:async_hooks";
import { Toolpass, PermissionDenied, guarded } from "toolpass-client";

const tp = new Toolpass(); // reads TOOLPASS_URL and TOOLPASS_API_KEY
const currentUser = new AsyncLocalStorage();

const writeThing = guarded(tp, "demo", "thing.write", "thing:{thingId}", { user: currentUser })(
  async ({ thingId }) => `wrote thing ${thingId}`, // your real action goes here
);

for (const who of ["admin@example.com", "dana@example.com"]) {
  try {
    console.log(who, "->", await currentUser.run(who, () => writeThing({ thingId: "1" })));
  } catch (e) {
    if (!(e instanceof PermissionDenied)) throw e;
    console.log(who, "-> refused:", e.decision.reason);
  }
}
```

```sh
TOOLPASS_URL=http://localhost:8080 TOOLPASS_API_KEY=change-me node quickstart.mjs
```

## 4. Connect a real system

Pick the system your agent acts in, follow its [integration page](integrations/README.md) to create
a read-only credential, and add a connection to `toolpass.yaml`. For example, Jira:

```yaml
connections:
  - id: jira-main
    integration: jira
    url: https://acme.atlassian.net
    username: toolpass-bot@acme.com
    credential: env:JIRA_TOKEN
```

Then check the file and the credential before you rely on it:

```sh
export JIRA_TOKEN=...              # the token from the integration page
export TOOLPASS_API_KEY=change-me  # validate reads api_key when the file has one
toolpass validate -config toolpass.yaml
toolpass probe    -config toolpass.yaml -connection jira-main
toolpass check    -config toolpass.yaml -connection jira-main \
  -user you@acme.com -action DELETE_ISSUES -resource issue:PAY-123
```

`toolpass catalog jira` lists the actions you can ask about. The integrations that sign with a
private key (a GitHub App, Google service accounts, Snowflake key pairs, Salesforce JWT, Microsoft
365 certificates) need `pip install "toolpass[crypto]"`; the Docker image has it.

## Next

- [Architecture](concepts/architecture.md): how a check flows, what is cached, and the trust boundaries.
- [Deploy](guides/deploy.md): in-process or as a server, with Docker, pip or Helm, and how to reach it over TLS.
- [Add toolpass to your agent](guides/agent-tools.md): the adapters for Strands, LangChain and
  LangGraph, MCP, the OpenAI Agents SDK, the Claude Agent SDK, Google ADK, CrewAI, Pydantic AI,
  LlamaIndex, and the TypeScript client.