Get it running, and ask it something real

By the end of this you will have the whole stack up, an agent that answers from your own files, and — this is the part that matters — you will have watched it refuse to do something, on purpose.

Budget about thirty minutes, most of it waiting for images to pull.

You need Docker with Compose, and a key for an AI gateway or model provider.

1. Bring the stack up

git clone https://github.com/tamebi-ai/nextcloud-ai
cd nextcloud-ai
cp .env.example .env

Open .env and fill in four values. Three of them are secrets you invent:

AI_GATEWAY_API_KEY=# your model access
TAMEBI_PROXY_SECRET=$(openssl rand -hex 32)   # proves a caller is the Nextcloud app
TAMEBI_APPROVAL_SECRET=$(openssl rand -hex 32)# signs confirmations
ONLYOFFICE_JWT_SECRET=$(openssl rand -hex 32) # shared with the document server

Then:

docker compose up -d --build

Give it a couple of minutes. docker compose ps should show every service up, and nextcloud-ai-db-1 as healthy.

2. Wire the parts that cannot configure themselves

Four scripts. All are idempotent — running one twice is safe, and you will run them again after changing anything.

./scripts/setup.sh      # connects Nextcloud to the OnlyOffice document server
./scripts/oidc.sh       # makes Nextcloud the agent's identity provider
./scripts/theme.sh      # applies the design tokens and logos
./scripts/webhooks.sh   # tells the content index when a file changes

oidc.sh is the one worth pausing on. There is no external identity provider here: Nextcloud issues the tokens and accepts them. That is what makes the token's subject equal to the Nextcloud username by construction, rather than by a mapping somebody has to maintain.

3. Create a normal account and use it

Open http://localhost:8080 and log in as the administrator you configured.

Now create a second account — and use that one from here on:

docker exec -u www-data nextcloud-ai-nextcloud-1 php occ user:add \
  --display-name "Alex Martin" --email alex@example.com alex

This is not tidiness. The entire guarantee of this system is "the agent sees what the user sees", and an administrator sees everything. Pointing the agent at an admin account turns that sentence into "the agent sees everything" without changing a line of code or producing a single warning.

Setting the email is not optional either, though nothing will fail without it: it is what publishes the account into Nextcloud's system address book, which is where the agent finds a colleague's address instead of inventing one.

4. Prove the invariant before you trust anything

./scripts/oidc-verify.sh alex <password>

Read its output rather than the exit code:

sub=alex aud=http://localhost:8091 iss=http://localhost:8080 ✓ OCS ✓ WebDAV ✓ CalDAV ✓ Deck ✓ no file of 'admin' listed or readable (404) ✓ account list refused (403)

The last line is the interesting one. It took a token that works — the four ticks above prove it — and tried to use it to read another account's files and to list the server's users. Both were refused, by Nextcloud, with nothing in our code involved.

Run this after any change to authentication. It is the only thing that proves the central property still holds.

5. Give it something to find

Log into Nextcloud as alex, and upload a document you actually know the contents of — a PDF or a Word file is a better test than a text file, because it exercises the conversion path. Put it somewhere with a real name, say /Contracts/.

6. Ask

Open the Tamebi app from the Nextcloud sidebar and ask something that requires reading, not listing:

Where does the contract say what happens if we terminate early?

Watch what happens under the reply. You should see the tool calls: a search that narrows, then a read that returns a passage rather than the whole file. The answer should quote the document.

If the agent says it cannot find anything, that is a legitimate outcome on the first try — the content index is filled by searches themselves rather than by a background crawler, so it warms up as it is used. Ask again in a minute. That behaviour is a direct consequence of the tool server holding no credential of its own: there is no privileged process that could crawl everything up front.

7. Now ask it to change something

Add an event to my calendar tomorrow at 3pm, "Contract review".

This time the agent stops and asks. The confirmation is not politeness and it is not written into the prompt: the tool declared itself as having an effect, and the approval requirement was derived from that declaration three services away. A tool that declares nothing at all is treated the same way, because the policy fails closed.

Approve it, and check the Calendar app. Then try:

Now make that file public so I can send the link to a client.

It will tell you it cannot. There is no tool for it — not disabled, not permission-checked: absent. One call would turn read access into exfiltration, and nothing about the request would look wrong, because the user is allowed to share that file.

What you have just seen

Four things, in order:

  1. The agent acts with your token, and Nextcloud is the only thing deciding what that permits.
  2. It reads documents rather than skipping them, and it retrieves passages instead of files.
  3. Anything with an effect stops for a human, driven by tool metadata rather than by prose.
  4. Some capabilities are absent by design, and absence is the enforcement.

To see how a single message actually travels through the five services — and to read the record it left behind — continue with Follow one message end to end.