Governance built in, not bolted on
Multi-tenancy, authorization, redaction, audit, tracing, and quotas are core modules — not plugins added after a breach. Jikji is designed for the day an agent platform has to answer to security, compliance, and finance.
Production readiness depends on explicit configuration: TLS termination, external secret storage, backup keys, database HA, and alert routing are operator responsibilities.
Identity, authorization, and a policy plane
Identity, authorization decisions, dynamic policy filtering, and service publication are four separate concerns behind four boundaries.
Tenancy & RBAC
Multi-tenant principals from scoped API keys, with resource:action scopes and hierarchical wildcards — plus IAM-style resource/action policies (allow/deny, down to a single tool) you can attach to a key and override at runtime with no restart. A policy simulator lets you validate and test a change before it goes live. Auth fails closed: anonymous principals never receive full access. In production mode the runtime refuses to start unless identity is enforced, keys carry explicit scopes, and a tenant principal is required at the request boundary.
Decision plane
A dedicated authorization plane evaluates tenant, principal, action, and tool context into allow, deny, or ask, each carrying a recorded reason. Tool executions land in a structured audit trail; full decision auditing — denials and asks, or every decision — is a configurable mode, and the trail can be HMAC hash-chained so tampering is detectable.
Dynamic filter chain
Composable request filters with conditional when predicates (time, environment, request attributes), approval gates, external policy calls with a circuit breaker, and permission modes auto / ask / deny — snapshot the live chain and roll it back to a known-good version at runtime.
Approve what agents expose
Agents can define their own UI and API surfaces; operators list, approve, or revoke each one from the service plane — via API, jikjictl service, or the dashboard — governed by the same policy path as every other action.
Policy is data — rules evaluate to allow, ask, or deny, and fail closed by default:
rubric: default_decision: deny # fail closed rules: - { id: allow-low-risk-reads, decision: allow, operations: [read], risks: [low] } - { id: ask-moderate-actions, decision: ask, operations: [write, execute, connect], risks: [moderate] } - { id: deny-high-risk, decision: deny, operations: [write, delete, execute], risks: [high] }
One service, many tenants, every user their own
An enterprise user model is built in. Stand up a service per tenant, let users reach it through scoped client keys, and give each one a private, personalized agent — without running a separate deployment for anybody.
A tenant is a service boundary
Each tenant has its own keys, data, memory, and policy. Stand up a service per tenant — or per team, customer, or environment — all on the same cluster, fully isolated from one another.
Every user is a scoped principal
Users reach a service as scoped principals — and a single service key can carry many of them. An actor identity on each request tells one end-user from another, so they stay separate without a key per person; scopes still decide what each may do, per request.
Memory isolated per user
Recall and ingest are partitioned by tenant and actor, and stamped onto every run from the principal — so one user never sees another's memory, even inside the same service.
Hyper-personalized responses
Each user's own facts and personal ontology shape how the agent answers them — a personalized context injected per principal, not one shared prompt for everyone.
Secrets, redaction, and injection defense
Vault & OAuth
An AES-GCM credential store (file or galley-backed) with rotation and access audit, managed by CLI, API, or dashboard. Providers can use env, vault, or OAuth credentials, with device login and token refresh — and inline keys are redacted from config export.
PII & secret redaction
The proof module detects and reversibly masks PII and secrets with stable placeholders before text is published or sent outbound, restoring values to the caller — and handling chunk boundaries safely in streaming responses.
Prompt-injection guard
Untrusted content is spotlighted and defanged, and taint tracking blocks sensitive tools once a run has ingested external data — defending against instruction-override and jailbreak attempts.
SSRF & egress control
Outbound HTTP from policy checks and injected extensions passes SSRF dialguard checks against explicit allowlists, blocking loopback and private ranges unless deliberately permitted.
Leakage stopped at the source
On runtime paths wired through Proof, values matching the enabled built-in, locale, or custom regex patterns can be masked before covered provider, tool, or log handling. Covered return paths can restore mapped values; drop mode intentionally skips restoration. Operators must configure patterns and verify each data path because unmatched formats and paths not wired through Proof remain outside this control.
Proof path, a value matching an enabled regex can become a stable placeholder such as [PII_EMAIL_1]. Unmatched values and paths outside Proof pass unchanged.Masked before it leaves
For paths explicitly integrated with Proof, enabled regex patterns redact matching inputs or tool outputs before the covered outbound or persistence boundary. Treat this as defense in depth: test every configured path and minimize sensitive input because regexes do not detect every format.
Unbroken for the real user
Reversible, stable placeholders are restored to the caller, so the end-user's view is intact — the masking round-trip is invisible to them, with nothing garbled or dropped.
Stream-safe & ephemeral
Placeholders are restored correctly even across streaming chunk boundaries, and the placeholder map is tenant-bound and never persisted — it lives only for the request.
See it, trace it, cap it
OpenTelemetry tracing
OTLP traces over gRPC or HTTP with W3C trace-context propagation and head sampling, correlation IDs through the request path, and structured access logs.
Metrics & profiling
A Prometheus /metrics endpoint with bounded label cardinality, agent run and step metrics, dispatch counters, and pprof endpoints for live profiling.
Usage limits & quotas
Track external provider quotas (rolling and weekly windows) and enforce internal per-tenant quotas, with admin endpoints, gauges, dashboard panels, and jikjictl provider usage. When a provider's window is hit (a 5-hour or 429 limit), dispatch durably retries after it clears instead of failing the work.
Cost guard
Set per-model cost tiers and budgets that back a cost guard — it also caps the multi-model trinity panels so an ensemble can't overspend. Manage tiers and budgets with jikjictl cost.
Live, attachable debugging
Live attach uses Unix PTY sessions over a WebSocket-backed terminal and is native-qualified on Linux; Windows ConPTY is not supported. Independently of terminal capability, the JSONL step trace replays a run end to end and /debug/pprof profiles the live process.
Built to survive the bad day
Recovery & durability
Validated per-step checkpoints with correlated replay guards, SQLITE_BUSY retry, and distributed lease managers that fail loudly rather than fabricating success.
Failure isolation
Per-provider circuit breakers, bounded queues with claim-and-settle leases, retry with backoff, and graceful drain on shutdown.
Supply-chain integrity
Signed marketplace installs (Ed25519 or HMAC) with verified checksums, and an egress firewall that fails closed if its filter can't install.
Channels & webhooks
A pluggable channel adapter interface drives agent runs from messaging platforms — a Telegram adapter today, built for more (Slack and beyond) — plus signed inbound webhooks, with per-chat tool scopes, allowlists, and rate limits.
Config & reload
Operator config export and hot reload over API, CLI, and dashboard, with deterministic, validated, test-covered config parsing.
Operator tooling
jikjictl for credentials, RBAC, policy, filters, audit, tracing, usage, and marketplace — plus a web dashboard that never stores keys server-side: a playground with snapshots, rollback, and in-place inquiry approval; filter views with circuit-breaker badges; IAM policies with the simulator; service-plane surfaces; usage panels; and vault management.
Backup & disaster recovery
Encrypted, integrity-checked backups of the datastore, with a restore-verify path that proves an artifact by restoring it into a throwaway store and checking the restored content matches the source at its own schema version. Run on demand with jikjictl galley backup and restore, or schedule recurring backups (leader-gated in HA, encryption required by default). Opt-in via backup.enabled; off by default.
Drive it all from the operator CLI:
jikjictl health # controller + dependency health jikjictl provider usage # external provider quota windows jikjictl config export # redacted live config snapshot jikjictl filter toggle --kind pii --enabled false # toggle a runtime filter jikjictl provider oauth reset codex # clear a quarantined OAuth token
Update it without taking it down
A platform that runs the business can't stop to be reconfigured. Jikji is built to change live — drain cleanly, reload config in place, and roll updates across a cluster that never stops serving.
Graceful drain
On shutdown the node stops accepting new work, lets in-flight runs finish, and only then exits — so a restart or redeploy never drops a session mid-flight.
Hot config reload
Export and reload runtime config over API, CLI, or dashboard without a restart — change providers, filters, and policy live, with deterministic, validated parsing.
Rolling updates via HA
With HA enabled, controllers share one database and elect a single leader for the singleton schedulers while every node serves traffic — so you update nodes one at a time and the cluster keeps running.