Architecture
How Khidmitak works
For architects, engineers and security teams evaluating Khidmitak: where it sits, how it reaches your systems, and the controls that hold when an agent acts. Everything here describes the product as it is today.
Where Khidmitak sits
Khidmitak is one service with its own PostgreSQL database for platform state. It sits between the people and agents that ask and the systems that answer. Your business data stays in your systems and is reached live, through adapters.
People
AI applications
Agents
- Agent runtime
- Tool registry & policy
- Context & semantics
- Identity & roles
- Proposals & approvals
- Activity & audit
Database adapters
MCP client
Model providers
Your systems
CRM · ERP · Finance · Internal databases · Line-of-business applications
Language models
How a request flows
A person asks
In their own words, in English or Arabic.
Khidmitak resolves who is asking
Their workspace, their role, and the tools that role allows.
The agent reads
Through adapters, read-only, with parsed queries, timeouts and row caps.
Changes become proposals
Stored with a hash and an expiry, waiting for approval. Nothing has changed yet.
Approved actions run once
Preconditions are re-checked, the change is applied, and everything is recorded.
Why this is hard
Connecting a model to a database takes an afternoon. These are the problems that appear once software acts inside real systems, on behalf of real people.
Identity
Whose authority is the agent using? It should be the person's own, scoped to their role, never a shared superuser.
Permissions
Reading is not writing. Every tool needs its own risk level and its own rules.
Context
Models need to know what the data means: which fields are sensitive, which tables matter, what “active customer” means here.
Approvals
Consequential changes need a person to see exactly what will happen, before it happens.
Protocols
PostgreSQL, REST, MCP, the ERP from 2009. Agents need one governed way in.
Discovery
New tools appear constantly. None should be callable just because it exists.
Observability
When something goes wrong, you need every step: which tool, which source, which parameters.
Lifecycle
Schemas and tools change. Decisions made against yesterday's version shouldn't silently carry over.
Connecting systems
A workspace can connect several systems. Each is reached through a database adapter, an MCP server or a model provider, and every connection passes through the same controls.
- Database adapters
- PostgreSQL today, through an adapter that uses separate least-privilege reader and writer credentials. Adapters are registered by kind, so new kinds of systems plug in behind the same contract.
- Schema introspection
- Khidmitak reads a source's structure (tables, columns, keys and relationships) into a versioned catalog with a fingerprint. Changes are executed only against the catalog version they were planned on.
- Semantic layer
- Teams add labels, descriptions and aliases to tables and fields, and mark which fields may be written.
- Field classification
- Each field can be public, internal, PII, sensitive or secret, and can be hidden from the model entirely.
- MCP servers
- Connected through the official MCP SDK. Tool lists come from an explicit discovery step, never from a network call on every question. Discovered tools start unclassified and blocked. Server hints such as readOnlyHint are never trusted, and a change to a tool's schema revokes its classification.
- Model providers
- Any OpenAI-compatible endpoint: a commercial API, a regional provider or a self-hosted model. Every call goes through the outbound network guard.
Tools and policy
The agent never calls a system directly. It calls tools, and every tool declares a risk level. Policy is evaluated on the server, fail-closed, on every single call.
| Risk level | Example | What happens |
|---|---|---|
| Read | Look up accounts, describe a table, run a query | Runs immediately |
| Write | Create a task, update a deal stage | Becomes a proposal a person must approve |
| External side effect | An MCP tool that sends or triggers something | Becomes a proposal a person must approve |
| Destructive | Delete anything | Never available to the agent |
| Unclassified | A newly discovered MCP tool | Denied until an administrator classifies it |
- Role defaults
- Read tools are open to every role. Tools that change data are open to members and above, never to viewers. Each workspace can disable a tool or narrow its roles.
- Tool families
- For each connected source: describe, query, propose an insert, propose an update. Purpose-built tools for the CRM vertical (nine that read, five that change data). Classified MCP tools. Built-in utilities for arithmetic, date differences and currency conversion.
Reading data
Reads are defended in layers, so no single mistake can turn a read into a write.
- A real PostgreSQL parser
- Model-written SQL is parsed by libpg-query, PostgreSQL's own parser compiled to WebAssembly, so it is validated exactly as the database will interpret it.
- Fail-closed rules
- Exactly one plain SELECT. No data-modifying CTEs, no SELECT … INTO, no locking clauses. Functions must be on an allowlist of side-effect-free built-ins. Every table must belong to the source's catalog, which also blocks probing pg_catalog and information_schema.
- Bounded execution
- Every read runs in a REPEATABLE READ, READ ONLY transaction with a statement timeout (10 seconds by default) and a cursor-enforced row cap (500 rows by default), and is always rolled back.
- A separate reader credential
- Reads use their own credential. We recommend, and the demo uses, a database role that is read-only at the database level.
Changing data
Tools that change data can only propose. Execution is a separate step, triggered by a person.
- Proposals, not actions
- A side-effecting tool drafts the change (operation, record, fields and values), and Khidmitak stores it together with the current values of the fields it touches. Drafting changes nothing.
- Integrity and expiry
- Each proposal is sealed with an HMAC over its canonical content and expires (after 15 minutes by default). Approval must present the proposal's ID and the hash the person was shown.
- Who can approve
- Members can approve their own proposals; managers and above can approve anyone's. The agent has no way to approve.
- Exactly once
- Approval claims the proposal with a conditional pending → executing update, so concurrent or repeated approvals can't run it twice.
- Re-checked at execution
- Inside a transaction, the target row is locked and compared with the values recorded at proposal time. If anything changed, or the source's schema changed, execution stops. Each change must affect exactly one row.
- Atomic batches
- A multi-record proposal (up to 200 changes) runs in one transaction: all or nothing.
- No delete
- There is no delete operation anywhere in the agent's path. Records are updated or archived, and the writer credential needs no DELETE or TRUNCATE privilege.
What the model sees, and what it costs
The model works through tools, so it only sees what a question needs. The same design keeps usage small and predictable.
- No data in the prompt
- The system prompt holds the workspace name, the date, the user's role, the list of connected sources and the rules. No customer records.
- Filtered tool results
- Before a result reaches the model, hidden and secret fields are removed, PII and sensitive fields are masked unless the workspace allows them, and anything credential-shaped is redacted. Results carry their source.
- Hard limits per question
- At most six model calls per question, each tool result capped at 12,000 characters, and the last 30 messages of a conversation as context. Earlier tool outputs aren't replayed.
- No retrieval layer, no background agents
- Khidmitak has no embeddings or vector store, and no agent runs between questions. Workspace insights are computed by rules, not by a model.
Identity and access
- Sign-in
- Email and password (at least 12 characters) through Better Auth. Sessions last seven days and revocation takes effect immediately.
- Browser sessions
- HttpOnly, Secure, SameSite=Lax cookies. No tokens in browser storage.
- Roles per workspace
- Owner, admin, manager, member and viewer, checked on the server for every request. There is no global role and no automatic promotion.
- Workspace isolation
- Every query on workspace data is filtered by workspace. Another workspace's records are indistinguishable from missing ones.
- Request forgery
- Requests that change state must come from a trusted origin and carry a JSON body.
- Rate limits
- Sign-in attempts and public forms are limited per client IP; chat messages and approvals per user.
Credentials and outbound connections
- Encrypted credentials
- Database passwords, API keys and MCP tokens are encrypted with AES-256-GCM. Configuration rows hold only a reference.
- Write-only
- Credentials can be set through the API but never read back, and they never reach a model, a log or the audit trail.
- Outbound network guard
- Every connection to a configurable endpoint (model provider, MCP server or database host) is checked: HTTPS only for web endpoints, and a host that resolves to a private, loopback, link-local or cloud-metadata address is refused unless an operator explicitly allowlists that host.
- No DNS rebinding
- The validated address is the one actually connected to. Redirects are re-validated (three at most), and responses are capped at 2 MB and 30 seconds.
- Egress allowlist
- Outbound connections can optionally be restricted to an explicit list of hosts.
Audit and observability
- Append-only audit trail
- Proposals, approvals, executions, rejections, and membership and configuration changes are recorded in an audit table that a database trigger keeps append-only. Entries hold identifiers and field names, never full records or secrets.
- Agent run trace
- Every answer records each step: the tool, the policy decision, the duration, the arguments, and the source the data came from.
- Activity feed
- One timeline for human edits, agent runs, approvals and system events.
- Source health
- Connection tests record each source's health and last error.
Deployment
- Two planes
- Khidmitak's own state (workspaces, users, policies, proposals, audit) lives in its PostgreSQL database. Your business data stays in your systems and is queried in place, never bulk-copied. Conversation history keeps the answers that were shown.
- A standard container
- One API container plus PostgreSQL, with no dependency on a specific cloud, so it can run where your policies require.
- Explicit migrations
- Schema migrations are a release step, never run at startup.
- Your model
- Point it at the model provider of your choice, including a self-hosted one.