A lightweight HTTP bridge that lets you call Google Gemini Gems (custom AI personas)
from any HTTP client -- n8n, curl, or your own code -- without re-sending large system
prompts on every request.
The official Gemini API does not expose Gem IDs. Without gemBridge, you must include your
full system prompt and persona instructions in every API call, which is verbose, expensive,
and error-prone. gemBridge authenticates via browser session cookies (using
HanaokaYuzu/Gemini-API) and forwards requests
to the correct Gem on your behalf.
Note: This approach depends on Google browser session cookies that expire every 2-4
weeks. Cookie rotation takes about 2 minutes and is the main ongoing maintenance task.
Best treated as a personal or internal tool rather than a public-facing service.
/reload -- no restart needed when cookies expiretouch .debug/health endpoint for monitoring and uptime checksgit clone ssh://theitguys@git.code.sf.net/p/call-a-gemini-gem-from-api/code gemBridge
cd gemBridge
cp .env.template .env
Edit .env and fill in the two cookie values:
__Secure_1PSID=your_value_here
__Secure_1PSIDTS=your_value_here
See docs/cookies.md for step-by-step instructions on getting these values.
Docker (recommended):
docker compose up -d
Direct (Python venv + systemd):
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
./start.sh
For full setup instructions including success indicators at each step, see
docs/setup.md.
curl -s -X POST http://127.0.0.1:8000/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "Summarise this in one sentence: ..."}'
curl -s -X POST http://127.0.0.1:8000/generate \
-H "Content-Type: application/json" \
-d '{
"prompt": "Draft a reply to this email: ...",
"gemId": "your-gem-id-here"
}'
{ "text": "Here is the response from Gemini..." }
curl -s http://127.0.0.1:8000/health
{
"status": "ok",
"uptime_seconds": 3600,
"debug_mode": false,
"psid_configured": true
}
If psid_configured is false, your cookies have expired. See
docs/operations.md for rotation steps.
.env)curl -s -X POST http://127.0.0.1:8000/reload
| Field | Type | Required | Description |
|---|---|---|---|
prompt |
string | Yes | The message to send to Gemini |
gemId |
string / null | No | Target Gem ID. null uses the default assistant |
model |
string / null | No | Override the Gemini model. null uses the default |
All configuration lives in .env in the project root. This file is gitignored and never
committed. Copy .env.template to get started.
| Variable | Required | Default | Description |
|---|---|---|---|
__Secure_1PSID |
Yes | -- | Google session cookie |
__Secure_1PSIDTS |
Yes | -- | Google session companion cookie |
PORT |
No | 8000 |
Port the server listens on |
HOST |
No | 0.0.0.0 |
Network interface to bind |
LOG_ROTATION |
No | 1 day |
How often to rotate the log file |
LOG_RETENTION |
No | 7 days |
How long to keep old log files |
TEST_GEM_ID |
No | -- | Gem ID used by the test suite |
| File | Contents |
|---|---|
| docs/setup.md | Complete first-time setup for Docker and venv paths |
| docs/operations.md | Day-to-day reference: status checks, cookie rotation, logs, troubleshooting |
| docs/cookies.md | How to extract and refresh Google session cookies |
| docs/n8n.md | Connecting gemBridge to n8n |
Add an HTTP Request node:
| Setting | Value |
|---|---|
| Method | POST |
| URL | http://<gembridge-host>:8000/generate |
| Body Content Type | JSON |
| Body | { "prompt": "{{ $json.prompt }}", "gemId": "your-gem-id" } |
The response contains { "text": "..." } -- reference it downstream as {{ $json.text }}.
See docs/n8n.md for the full guide including importing via cURL.
This project is released under the MIT License.
The gemini-webapi dependency is licensed under the GNU Affero General Public License v3.