- Python 70%
- HTML 28.1%
- Dockerfile 1.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
15-minute graceful browser idle shutdown. Exact head passed 24 tests and live accelerated-clock stop/relaunch checks. |
||
| agent_pocket_money | ||
| docs | ||
| patches | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CHANGELOG.md | ||
| compose.yaml | ||
| Containerfile | ||
| LICENSE | ||
| Manager.Containerfile | ||
| private_encrypted_files.zip.enc | ||
| pyproject.toml | ||
| README.md | ||
| SECURITY.md | ||
| UPDATING.md | ||
Agent Pocket Money
Your agent gets pocket money, not the wallet.
An MCP service that gives agents pre-approved browser skills instead of browser control.
You write each task once as a skill ("buy the item in product_url with this card, to
this address, up to this price"). A requesting agent can only pick a skill and fill in
its declared parameters. A second, narrow agent then does the work in a real, logged-in
browser and returns a short result. The requesting agent never sees the browser, your
logins, your cookies or your other cards.
Why
Without it, your agent drives the browser itself:
flowchart LR
I1["Prompt injection<br/>(web page, mail, document)"] -.->|"new goal"| A1["Main agent"]
A1 -->|"full browser control"| B1["Logged-in browser<br/>every card, every address,<br/>account settings"]
With Agent Pocket Money, a compromised agent still only reaches the narrow interface:
flowchart LR
I2["Prompt injection"] -.->|"new goal"| A2["Main agent"]
A2 -->|"submit_task(skill, params)"| G{"Narrow MCP<br/>interface"}
G -->|"goal, free text,<br/>undeclared param"| X["Rejected,<br/>nothing queued"]
G -->|"declared params only"| W["Buying agent<br/>task = your skill text:<br/>this card, this address,<br/>this price ceiling"]
W --> B2["Logged-in browser"]
W -.->|"short result only"| A2
A compromised main agent has nothing to steer with. The interface has no field for a goal or an instruction, so the buying agent's task is always the skill text you wrote. The worst a hijacked caller can do is run one of your skills with different parameter values.
Two honest limits, both explained in SECURITY.md:
- Put anything the caller must not choose into the skill text. The seeded
buy_itemskill does this for the payment method: write your card into its "Fixed payment method" line before enabling it. The delivery address is still a parameter; fix it the same way if the caller should not choose it. - The buying agent follows the skill as instructions; nothing technically locks the card. Keep a spending limit on the card itself.
Quick start
cp .env.example .env && chmod 600 .env
# fill in four distinct tokens (openssl rand -hex 32)
docker compose up -d --build # or: podman compose up -d --build
docker compose exec control codex login --device-auth
Then open the Manager on http://127.0.0.1:8080 to create a browser profile and sign in
to your shop, and the admin UI on http://127.0.0.1:8090 to wire a skill to that
profile. Point your agent at http://127.0.0.1:8090/mcp with the requester token. The
full walkthrough is in docs/setup.md.
You need Docker or Podman Compose, a ChatGPT plan that includes Codex (the buying agent is the official Codex CLI under your own login), and a CloakBrowser licence key (a free one is enough).
Browser idle shutdown
The control service gracefully stops running browser profiles after 15 minutes without
an active job (checked every 15 seconds). The persistent profile/cookies are retained;
the next job launches the same profile automatically. Any queued, running, paused,
pausing or cancelling job protects all profiles. An operator Hold jobs on a profile
also prevents idle shutdown, including during manual browser work; release it afterwards.
Page animation and background network traffic do not extend the timeout. A control-service
restart starts a fresh idle window. Set BROWSER_IDLE_SECONDS=0 to disable, or another
nonnegative duration in seconds to override the default of 900.
Documentation
| Document | What it covers |
|---|---|
| docs/setup.md | Prerequisites, installation, worker login, first run, native mode |
| docs/requester-interface.md | The MCP tools a requesting agent gets, results and error codes |
| docs/how-it-works.md | How a job runs, job states, pause and cancel, skills and learning |
| docs/browser.md | Browser engine, licence key, fonts, profile settings, diagnostics |
| docs/development.md | Code layout, tests, smoke checks, known limits |
| SECURITY.md | What is and is not protected; read it before storing a real credential |
| UPDATING.md | Updating the upstream components |
| CHANGELOG.md | Release notes |
Licence and contributions
This project is licensed under the GNU Affero General Public License v3.0 only: you may use, run and modify it, and if you pass it on or let others use a modified version over a network, you must make your changes available under the same licence.
Fixes are welcome. By submitting a contribution you license it under the AGPL-3.0 and additionally grant the maintainer a perpetual, irrevocable, royalty-free right to use, modify and relicense it under any terms.
The patch under patches/ is derived from CloakBrowser Manager (MIT, notice alongside).
The CloakBrowser browser binary, the Codex CLI and any fonts are not part of this
repository and keep their own licences.
Maintainer's private archive
private_encrypted_files.zip.enc is the maintainer's own encrypted backup. It is useless
without its passphrase and is not needed to run the service. To restore it (openssl asks
for the passphrase):
openssl enc -d -aes-256-cbc -pbkdf2 -iter 1000000 \
-in private_encrypted_files.zip.enc -out /tmp/private_files.zip
mkdir -p ~/.local/share/agent-pocket-money
unzip /tmp/private_files.zip -d ~/.local/share/agent-pocket-money/ && rm /tmp/private_files.zip