AI_glue – drop-in audit and governance for OpenAI and Anthropic apps
AI_glue is an open-source transparent proxy that adds logging, spend tracking, PII detection, and governance to AI apps with zero code changes. It supports proxy and wrapper modes, multi-instance aggregation, and provides a unified dashboard with executive and audit views.
Notifications You must be signed in to change notification settings
Fork 0
Star 0
BranchesTags
Open more actions menu
Folders and files
NameName
Last commit message
Last commit date
Latest commit
History
13 Commits
13 Commits
docs
docs
examples
examples
routes
routes
src
src
static
static
templates
templates
tests
tests
.env.example
.env.example
.gitignore
.gitignore
CLAUDE.public.md
CLAUDE.public.md
CONTRIBUTING.md
CONTRIBUTING.md
LICENSE
LICENSE
README.md
README.md
app.py
app.py
governance.yaml.example
governance.yaml.example
requirements.txt
requirements.txt
Repository files navigation
Drop-in AI observability and governance for OpenAI and Anthropic applications.
What ai_glue gives you
Every AI call logged — provider, model, tokens, cost, latency, project, session
Spend visibility by project, team, and environment
PII detection with per-call flag review workflow
Hard governance rules — block unapproved models, enforce cost caps and rate limits
Multi-instance aggregation — dev, staging, and prod in one unified dashboard
Role-split views: engineering audit log, executive spend summary, per-instance breakdown
Add governance to existing apps with one environment variable change — no code rewrites
What ai_glue is not
ai_glue does not replace your AI stack. It has no opinion on prompts, agents, RAG pipelines, or orchestration. It sits between your applications and model providers to add governance, auditing, spend visibility, and policy enforcement. Think of it as a transparent proxy with a dashboard — not a framework.
Deployment models
Evaluating / self-hosted — you are both the operator and the user. Clone it, add your own API key to .env, run it on your machine. The quickstart below covers this case.
Team deployment — IT deploys one ai_glue instance on a shared server with the organization's API key in .env. Individual developers never touch an API key. They change one environment variable on their machine and everything is logged, governed, and visible on the shared dashboard.
┌─────────────────────────────────────┐ dev laptop │ ai_glue server │ ANTHROPIC_BASE_URL ───►│ .env: ANTHROPIC_API_KEY=sk-org-... │──► Anthropic API │ dashboard: http://ai-glue.internal │ └─────────────────────────────────────┘
Quickstart (local / evaluation)
git clone https://github.com/simonhansedasi/ai_glue.git cd ai_glue pip install -r requirements.txt cp .env.example .env # add your API keys cp governance.yaml.example governance.yaml python examples/governance_demo.py # no API keys needed python app.py # http://localhost:5010
Two integration modes
Mode 1 — Proxy (zero code changes)
Point existing apps at ai_glue instead of the real provider. One environment variable per app:
Anthropic
ANTHROPIC_BASE_URL=http://your-host:5010/proxy/anthropic
OpenAI
OPENAI_BASE_URL=http://your-host:5010/proxy/openai/v1
Every call is intercepted, logged, and governance-checked. The app receives the real response unchanged. Streaming is fully supported — the proxy passes the stream through and captures token counts and latency at the end.
Tag calls with optional headers for project and session labeling:
X-Aiglue-Project: hr-bot X-Aiglue-Session: user-123
If no headers are present, calls fall back to AIGLUE_DEFAULT_PROJECT / AIGLUE_DEFAULT_SESSION from .env.
Mode 2 — Wrapper (new apps or when you control the code)
from src import GluedClient
Anthropic — same API as anthropic.Anthropic()
client = GluedClient("anthropic", session_id="user-123", project="hr-bot") response = client.messages.create( model="claude-sonnet-4-6", max_tokens=512, messages=[{"role": "user", "content": "..."}], )
OpenAI — same API as openai.OpenAI()
client = GluedClient("openai", session_id="user-123", project="support-bot") response = client.chat.completions.create( model="gpt-4o", max_tokens=512, messages=[{"role": "user", "content": "..."}], )
Governance
Edit governance.yaml to configure rules. Changes apply immediately — no restart needed.
model_allowlist: # hard-block calls to unapproved models (403)
- claude-sonnet-4-6
- gpt-4o
pii_detection: true # flag prompts containing emails, SSNs, phones, credit cards
pii_allowlist: # exact strings that should never trigger a PII flag
projects: hr-bot: daily_cost_cap_usd: 5.00 # hard-block once daily spend hits cap rate_limit_per_hour: 100 # hard-block sessions that exceed call frequency
PII detection is regex-based (not ML). Hard-blocking violations are never logged — the call was never made. PII flags are logged as warnings and do not block calls.
Security note: governance.yaml becomes a sensitive file if you use the team API key mapping feature (see below), since it maps key prefixes to real project names. Treat it like .env in production — restrict filesystem permissions and do not commit it. governance.yaml is gitignored by default for this reason.
Dashboard
All three views draw from the same unified dataset merged across all instances.
/ — Audit (engineers / team leads)
Full call log. Every call from every instance in one table. Summary cards, daily charts, and by-project/by-model breakdowns are all merged across instances. Per-session drilldown shows individual turns, tool calls, and highlights flagged PII inline. Filters: ?project=X, ?session=X, ?flagged=1.
/executive — Executive view (leadership)
Non-technical. No session IDs, no model names. Cards: Total AI Spend, Projects Active, Conversations, Risk Flags. Charts: Spend by Project, Daily Spend trend. Unreviewed PII flags and governance blocks surface as a risk callout with a "Mark all reviewed" action.
/aggregate — Per-instance breakdown
One panel per instance with its individual summary, by-project table, and by-model table. Useful for comparing dev vs. staging vs. prod activity side by side.
Multi-instance aggregation
Run one ai_glue instance per environment. A parent instance pulls /api/summary from each child and merges everything into a single unified view.
Dev instance ──┐ Staging instance ─┼──► Parent instance ──► unified /, /executive, /aggregate Prod instance ──┘
To add a child — edit governance.yaml on the parent only, no code changes:
aggregator: children:
- name: prod
url: http://prod-host:5010
- name: staging
url: http://staging-host:5010
Set AIGLUE_INSTANCE_NAME on each child so it appears with a meaningful label in parent views.
Per-team API key mapping
Issue each team a synthetic key with a recognizable prefix. Teams swap their real provider key for it — no other changes needed. The proxy detects the prefix, tags all calls with the team's project name, and substitutes the real API key before forwarding. This enables centralized billing, per-team spend attribution, and chargeback models without distributing raw provider keys.
teams: sk-aiglue-eng: name: engineering sk-aiglue-marketing: name: marketing
Add spend caps or rate limits per team by adding the team name to projects: in governance.yaml.
What gets logged
Field Description
ts UTC timestamp
provider anthropic / openai
model exact model string
session_id caller-supplied, auto-detected, or default
project caller-supplied, auto-detected, or default
input_tokens from API response
output_tokens from API response
cost_usd estimated from token counts
latency_ms wall time
prompt_hash MD5 of prompt
raw_prompt full text (if AIGLUE_LOG_RAW=true)
raw_response full text (if AIGLUE_LOG_RAW=true)
gov_flags JSON array of warning strings
error exception message if call failed
reviewed_at timestamp when flags were acknowledged
Set AIGLUE_LOG_RAW=false in .env to store only the hash when prompt content is sensitive. Restrict filesystem permissions on audit.db in production — it contains call metadata and optionally raw prompts.
Training data export
ai_glue logs every prompt and response, which means your audit database doubles as a conversation dataset. The /export/training endpoint turns logged conversations into JSONL you can use for fine-tuning, content mining, or building provider-independent capability baselines.
This is particularly useful when a model you depend on is deprecated or sunsetted — if your conversations were logged through ai_glue, you have the raw material to fine-tune a replacement rather than starting from scratch.
Export a single conversation
On any session page (/session/), click Export JSONL to download that conversation as a single-session JSONL record.
Via URL directly:
/export/training?format=session&session=
Export all conversations for a project
On any project page (/project/), click Export all conversations to download every session for that project.
Via URL:
/export/training?format=session&project=
Output formats
format=session — one JSONL line per full conversation, with alternating user/assistant turns. Compatible with most fine-tuning pipelines.
{ "session_id": "conv-a3f9b2", "project": "support-bot", "model": "claude-sonnet-4-6", "messages": [ {"role": "user", "content": "How do I reset my password?"}, {"role": "assistant", "content": "You can reset your password by..."}, {"role": "user", "content": "I don't see that option."}, {"role": "assistant", "content": "Try navigating to..."} ] }
format=turn (default) — one JSONL line per API call, as isolated prompt/completion pairs. Useful for token-level analysis or simpler fine-tuning setups.
{"prompt": "How do I reset my password?", "completion": "You can reset your password by...", "model": "claude-sonnet-4-6", "session_id": "conv-a3f9b2", "project": "support-bot", "ts": "2026-05-15 10:00:00"}
Filters
All filters can be combined:
Param Example Effect
project ?project=hr-bot Only conversations from this project
session ?session=conv-abc Only this session
model ?model=gpt-4o Only calls made to this model
since ?since=2026-01-01 Only calls on or after this date
exclude_flagged ?exclude_flagged=true Drop calls with PII or governance flags
Notes
Calls are only exportable if AIGLUE_LOG_RAW=true (the default). Rows logged with AIGLUE_LOG_RAW=false are excluded from training exports.
The export queries the local instance's database only. Cross-instance export requires fetching from each child directly.
The user message for each turn is extracted from the end of the stored prompt string — the format is stable for standard single-user, single-assistant conversations.
Tests
pytest tests/ -v
27 tests. No API keys required. All LLM calls are mocked.
Stack
Python 3.7+, Flask, SQLite
Chart.js (CDN, no build step)
Anthropic SDK, OpenAI SDK
Environment variables
Variable Default Description
ANTHROPIC_API_KEY — API key used by the server to forward calls. In team deployments, only the server's .env needs this — individual developers do not.
OPENAI_API_KEY — Same as above for OpenAI.
AIGLUE_DB audit.db Path to SQLite audit database
AIGLUE_LOG_RAW true Store full prompt/response text
AIGLUE_DEFAULT_PROJECT proxy Project label for untagged proxy calls
AIGLUE_DEFAULT_SESSION proxy Session label for untagged proxy calls
AIGLUE_INSTANCE_NAME (AIGLUE_DEFAULT_PROJECT) Label shown in parent aggregator views
License
MIT
About
No description, website, or topics provided.
Resources
Readme
License
MIT license
Contributing
Contributing
Uh oh!
There was an error while loading. Please reload this page.
Activity
Stars
0 stars
Watchers
0 watching
Forks
0 forks
Report repository
Releases
4 tags
Packages 0
Uh oh!
There was an error while loading. Please reload this page.
Contributors
Uh oh!
There was an error while loading. Please reload this page.
Languages
Python 70.2%
HTML 24.9%
CSS 4.9%