Kindgi 0.2.0
Released October 28, 2026. For the docs of this version, see docs.kindgi.com/v0.2.0.
There was no 0.1.11 release: everything its preview (0.1.11-rc.0) brought
is in 0.2.0, so upgrade straight from 0.1.10.
Security fixes
Section titled “Security fixes”-
On a runtime without an authorization store, the tenant's settings are a tenant admin's to change, as they are with one. Such a runtime checked nothing on them, so a member key, or anyone signed in, could change the model providers, policies, adapters, trusted signing keys and the sign-in provider catalog. Anyone else now gets
403 permission-denied, and reading them stays open to everyone. The outgoing webhook endpoints and the compliance evidence need a tenant admin for reads too. Without a store, a tenant admin is the deployment's API token, anadminkey, or a console signed in with either; amemberkey, a key limited to a project and a person signed in with an identity provider or an emailed link aren't. Deploying doesn't change. -
The CLI's sign-in file is your account's alone:
kindgi auth loginwrites~/.kindgi/config.json0600, in a~/.kindgithat's0700. Before, both took the default mode, so with the usual umask another account on the same computer could read the API key. A file or folder an older CLI wrote is fixed the next timekindgi auth loginruns: the new key goes into a new0600file that replaces the old one, so a program that already had the old file open can't read the new key through it. To fix yours now, runkindgi auth loginagain, orchmod 600 ~/.kindgi/config.json && chmod 700 ~/.kindgi(Sign the CLI in). The CLI's other files that hold keys are owner-only too:kindgi key createsets a~/.kindgi/keysfolder that's looser than0700to0700(private keys were already0600), a new.env.<name>file thatkindgi env setorkindgi env pullmakes is0600(one that's already there keeps its mode), and so iskindgi feedback's draft in the temp folder.kindgi devwrites.kindgirc.jsonand.kindgi/dev/runtime.env, which hold the dev runtime's tokens, as a new0600file each time too, where it wrote into the file that was there. A symlinked one stays a link, and the file it points to is the one replaced;kindgi feedback's files in~/.kindgi/feedback/now do the same, where a plain file took a link's place. One of these files, or~/.kindgi/config.json, that isn't a regular file, or is a link to one such as/dev/null, is left as it is: for.kindgirc.json,kindgi devsays it couldn't write it, and the banner names.kindgi/dev/runtime.envas where the token is. On Windows, the modes don't change, and.kindgirc.json,.kindgi/dev/runtime.envand~/.kindgi/config.jsonare written in place, as before;kindgi feedback's files are still replaced there. -
A tool's error is masked before a run shows it. What a tool's error says reaches the run's record, its events, the console and the model. A pack tool's own secrets of four characters or more are now taken out of it, as written or as a JSON string writes them, as its connection tokens already were. Then secret-shaped text is masked: a Kindgi token, a
Bearervalue, a URL's password and a URL's secret query or fragment value, such as?token=orX-Amz-Signature=. Before, an error that quoted one of them showed it there (When a call fails). -
An HTTP tool's or an MCP endpoint's credential no longer shows in a failed call's error: where the service quotes back what the call sent, the runtime puts
[redacted]in its place, in the call's result, the run's events and the logs. This covers an HTTP tool'sauthorization.secretRef, and an HTTP MCP endpoint'ssecretRef,auth(a Basic credential'suser:password, and the password alone), OAuth access token, and a credential an earlier runtime let it keep inconfig.headers. Before, a credential with no known shape stayed in the error as the service wrote it (Store the secret). -
A hard revoke on Azure Key Vault purges the secret where the vault allows it: every version is disabled, the secret deleted, then purged. Before, it was only deleted, so Key Vault kept it recoverable for the vault's retention period with every version enabled, and setting the name again in Kindgi recovered it, old values and all. Where Kindgi can't purge, under purge protection or without permission to read and purge deleted secrets (
Microsoft.KeyVault/vaults/secrets/purge/action), every version of the copy kept is disabled, and asecretswarning says why (Revoking for good).
-
Improve can try a cheaper model or another temperature, and keeps one only when the decisions stay right. Mark the keys of the agent's model-settings block as for a settings block:
temperature,maxOutputTokens, and the model the turn prefers,model(withproviderId), itsenumlisting the models to try. A change there is kept only when no correction the current version passes fails, and when it's better, or no worse and cheaper beyond the spread. A suggested change'sevaluationsays which (rule:betterorcheaper), withcostUsdanddecisions. Name the model in one place: a version that names it in the block and in the agent too is refused at publish and at deploy (Let it try a cheaper model or another temperature). -
kindgi proposals improvedrafts the agent's instructions:--tier=prompt, with the--providerand--modelthat draft them and--drafts(1 to 5, 3 by default). The agent version must take its instructions from a prompt block it pins.--class-weightspicks whose corrections an Improve run learns from, as forkindgi eval-runs start(Draft the agent's instructions instead). -
Ask what an Improve run would cost before you start it:
POST /v1/proposals/improve/estimate, with the body an Improve run would start from, answersestimatedCostUsd: the replay count times the version's mean cost over its recent completed runs, capped at--max-cost. It starts nothing. In the TypeScript client, it'sproposals.improveEstimate(Start an Improve run). -
An Improve run started by hand works in its scope's project: for a project or segment scope, that project; for the tenant or an org,
--pass-project=<project-id>(projectIdin the API and the clients), else the agent version's. So an Improve run scoped to another project can use test cases built from that project's runs (Start an Improve run). -
Improve under
kindgi dev: an Improve run, a draft and an evaluation work as on a deployed runtime, for the whole tenant. Making a suggested change live writes it into the pack's files, each block's new version and content into the block's own file, andkindgi devreloads; an undo is done there, with git. When a block's file changed since the suggested change was made, the request is refused with409 promotion-superseded, naming the file (Underkindgi dev). -
A pack brings its data blocks: one JSON file per block in its
blocks/folder, in the shapekindgi blocks publishtakes, and a long template can have its own file (templateFile).kindgi buildchecks each block and refuses a pack whose blocks don't hold up, naming each file.kindgi deploypublishes them before the agents that use them, and an agent pins the pack's own version of each. A version never changes: a deploy that brings one the runtime holds with other content is refused, so give the block a new version. Underkindgi dev, blocks come from the pack's files only, and a publish there is refused with409 registry-read-only. A Python, Java or Scala pack with blocks needs akindgipackage orcom.kindgi:kindgi-packthat reads them:kindgi buildrefuses one from before blocks, naming the release to upgrade to (Keep them in the pack). -
Edit a settings block as fields, and update its agents in one step: each key gets a field from the block's JSON Schema (a choice, a number within its limits, a checkbox, a text) or, where none fits, a JSON box, and Edit as JSON goes back to the whole value as JSON. One button publishes the block, then derives a new version of each agent in the project that uses it, and pins it or asks for approval where the release gate policy and your access allow. Its label says which: Save and pin, Save and ask for approval or Save and derive versions. Retry the failed steps picks up where a step failed.
-
A correction can say what the agent should have done: the tool calls it should have made, with the arguments that matter, and the tools it shouldn't have called (
kindgi judgments add --correction, runtime 0.2.0 or later). When you try a version on test cases built from the run, it checks what that version does against it (Say what it should have done). -
kindgi judging-rulesandkindgi judging-queue: manage a project's judging rules, and the queue of runs they pick for a person to correct, from the terminal.queue-recent, orcreatewith--queue-lastor--queue-since, catches a rule up on runs that ended before it was there:POST /v1/projects/{projectId}/judging-rules/{ruleId}/queue-recentin the API, andqueueRecent(queue_recentin Python) in the clients (Queue the runs to correct). -
The console shows which runs are corrected, and a new rule can queue recent runs: the runs list has a Corrected column and a corrected run's page a Corrected badge. Someone who can correct runs gets Next to correct, the next open run in the project's To correct queue. A new judging rule can Also queue its recent matching runs for correction now: How many recent runs, 1 to 1000, 100 by default (Queue the runs to correct).
-
Your coding agent can fix what the experts corrected: the new
kindgi-fix-correctionsskill, whichkindgi initandkindgi skills syncinstall, pulls an agent's runs marked wrong, sorts each correction to where it belongs (a tool's code, a setting, an approval rule or the agent's instructions) with a pack test for each, publishes a new version and asks a person to make it live. It never raises a limit or drops a check (Fix what the experts corrected). -
A suggested change names the corrections it rests on: its
evidence.judgmentIdslists up to 100 of the ones on the cases it learned from, andevidence.judgmentCountsays how many when there are more. Each item of a test case lists its corrections injudgmentIds(Whose corrections it learns from). -
An Improve run refused for having nothing to work on says why: its
400 validation-failedcarriesdetails.reason,no-tunable-keysorno-pinned-prompt-block, for a client to match (Mark what Improve may change). -
Schedule Improve in the console: Schedule Improve, on the project's Schedules page or on an agent's Suggested changes page, makes the same schedule as
kindgi schedules create --improve, with the same defaults: what to improve, what better means, experts' corrections only, the scope, the cron (at most once an hour) and its time zone, the counts that start an Improve run, and what each run and each month may spend. It shows to someone who can change the project's schedules and start Improve runs (Schedule Improve in the console). -
An agent's page shows its Improve loop: after Recent runs, each section with its newest five: Corrected runs, with To correct; Test cases; Improve runs; and Suggested changes, which opens the agent's Suggested changes page (In the console).
-
The runtime image is pulled with your license key, from
registry.kindgi.com. The image isregistry.kindgi.com/kindgi/runtime, tagged with each release's version, and your license key is its password, with the usernamekindgi. There's no separate pull credential. A production key and a free non-production key pull the same image, until 14 days after the key's expiry date; a revoked key stops pulling within a few minutes. The Cloud Run and Azure Container Apps pages copy the image into your own registry by digest, so a key's expiry never stops a deployment (Pull the runtime image). -
Sign in at access.kindgi.com with your email address, as well as with GitHub. It emails a 6-digit code that works for 10 minutes, and gives you the same free non-production key. If your address is your GitHub account's primary verified email, either sign-in gives you the same key (Sign in with your email address).
-
Everyone gets their own key, at a company too. A company address's key is named after the company's domain, such as
acme.com, so the name the runtime prints at start is safe in shared logs, and one person's key can be revoked without touching anyone else's. If your company had one shared key, your next sign-in gives you your own, and the shared one keeps working until it expires (Your key's name). -
Renewing a key for someone who signs in by email:
kindgi license enroll --fortakes theem-id their key page at access.kindgi.com shows, as well as a GitHub login, and its help and messages say so (Renew the license key). -
kindgi auth registry --key-from <store>reads the license key from where a deployment keeps it, askindgi license renewdoes:file:…,env-file:…#NAME,gcp:…,azure:…oraws:…. So a deployment's own key logs in without passing through your shell. It's forregistry.kindgi.comonly (kindgi auth). -
Cloud Run module: how many backups, and where:
database_backup_retention,database_point_in_time_days(at most 7 onENTERPRISE, the module's edition, and at most as many days as backups kept) anddatabase_backup_location(a region or a multi-region,us,euorasia; a zone is refused at plan). Without them, Cloud SQL keeps 7 daily backups and 7 days of transaction logs, in the multi-region nearest the instance, which can be in another country. Setting them on a running deployment changes the instance in place, and the backups taken before stay where they were. They set the module's own instance only: withdatabase_host_instance, they're refused at plan (Cloud Run). -
A lost first admin key, minted again: for a tenant created without
firstAdmin,kindgi-runtime tenants admin-keyrevokes its "First admin" service account's live keys and mints one key carrying what the first did, printed alone on stdout. It's refused when one of those keys has a use recorded, unless--revoke-used.--dry-runsays what it would change, and each revoke and the mint are in the tenant's audit log, bysystem, with the--reasongiven (Serve many tenants). -
Java client: the helpers the TypeScript and Python clients have.
Comparisons.comparisonOf(run)reads a comparison eval run's result, typed (Compare a version on a test set).Webhooks.verifychecks a webhook Kindgi sends, andWebhooks.parseEventreads its typed event (Verify a webhook).SignedExports.verifychecks a signed export with the JDK's own crypto, so there's nothing extra to install (Export signed evidence). Scala apps call them from the Java client. -
Java client: the sign-in setup message.
SsoHandoff.forProviderbuilds what an admin sends whoever runs their identity provider: the OIDC or SAML URLs, what to send back, and a preset's console steps (Google, Entra, Okta, Keycloak). It's the same textkindgi sso providers startand the console show (Get what to send IT), with no network and no dependencies, for a JVM app with its own setup screen. -
Java and Scala: a tool can be an HTTP request, declared as data. A tool can end with
.http(spec), anHttpToolSpec(method, URL template, headers, authorization from a secret or a connection, request body, success statuses) in place of a handler. The runtime makes the request; calling the tool in the JVM throwsUnsupportedOperationException.{placeholders}may sit in the URL's path and query, never its host or port, and in a text body, each filled from the input, as in TypeScript's and Python's HTTP tools (Declare the request). -
Python, Java and Scala: a test fills a tool's env as a run does.
ToolContext.for_test(tool=...)(Python) andToolContext.forTest(tool, env, secrets)(Java and Scala) give a context whoseenvis what the tool declares, from the test's values or each schema's default (Give a tool per-project values). -
A tool can pause its run until another system answers. A TypeScript or Python pack tool that declares
pauseshands another system its call's link, and returnsctx.pause(). That system posts its answer to the link, as JSON, with no key: the answer becomes the call's result, and the run goes on. A pause waits 24 hours by default, 24 days at most.kindgi runs resumenames the wait and exits5, and--outputanswers it by hand; from an app,runs.resumeanswers it, andruns.getlists it underwaitingFor.tokens. The link is made fromKINDGI_PUBLIC_URL(Wait for another system's answer). -
A schedule, webhook trigger or mail trigger can name tools its runs call without waiting for a person's yes. A tool that asks for one when no person started the run (
needsApprovalWhenUnattended, any call with a person's connection, reads included, or, in a mail's run, a change or a use of the run's own mailbox) can be listed in the trigger'stoolsAllowedUnattended, by id, with--allow-unattended=<tool-id>onkindgi schedules create|update,kindgi webhooks register|updateandkindgi mail-triggers create|update. It lifts only that wait: the agent's and the tenant's approval rules still apply, and the run acts as the trigger's owner. Setting it takesadminon the project, a take-over keeps it, and each change is recorded astrigger-tools-allowed-unattended-set, on legal hold (Tools allowed unattended). -
Start runs from new mail: a mail trigger watches a Gmail or Outlook mailbox, its inbox or one folder or label in it, and each new mail starts a run of an agent or a flow, with the mail and the rest of its thread as the run's input. A trigger on a person's mailbox reads its owner's own mail, so it's personal. One on the company's mailbox takes a project admin, and is shared when a service account owns it. Its runs act as its owner. Mail is text from anyone, so in a run a mail started, a call that changes something, or that uses the run's own mailbox, waits for a person's yes unless a project admin lists the tool in the trigger's
toolsAllowedUnattended. A Microsoft 365 shared mailbox or a Google group isn't supported yet (Start runs from new mail). -
kindgi mail-triggers,/v1/mail-triggersand the clients:create,list,get,update,pause,resume,take-ownershipandunregister, as for schedules and webhooks, andfires, which lists a trigger's mail: the run each started, why one waits behind an earlier mail of its thread, or why it was skipped, refused or failed. A trigger'sstatusReasonsays why its mail starts no runs (connection-missing,owner-refused). The TypeScript client hasclient.mailTriggersand the Python clientclient.mail_triggers. A run a mail started says so:startedByandtrigger.kindaremail.kindgi exports createwrites the mail triggers and their fires (kindgi mail-triggers). -
Mail triggers in the console: a project's Mail triggers page lists each one with the mailbox it watches, why it isn't reading mail when it isn't, what it starts and its last mail, and New mail trigger makes one. A trigger's page shows its last 50 mails and what came of each, and pauses, resumes or removes it or changes its owner. An approval a mail's run waits on shows The mail it started from, as plain text, above the tool call, and the run names its trigger under Started by (In the console).
-
The
kindgi-usingskill finds a mail trigger in the console: asked what the support inbox did with a mail, it links the trigger's page, with its latest mails, what happened to each and the run it started, and the list of every run the trigger started (In the console). -
Connections: a tool acts in another app with an account someone connected. An admin registers the company's own Google OAuth client, Microsoft Entra app, GitHub App or LinkedIn app once, its secrets by reference. People connect on the app's own sign-in page, from the console's Connections page or from a run that waits for them, and the app's token goes into your own secret store. A tool declares the app and the permissions it needs (
needsSpec.connections), and each call gets the connection's current short-lived token inctx.connections: the model never picks an account. In a run no person started, a call with a person's connection, a read too, waits for that person's yes. A runtime offers connections withKINDGI_PUBLIC_URL,KINDGI_ENVand a secrets store, sokindgi devdoesn't (Connect your apps). -
Register the company's apps in the console: a tenant admin registers, changes and removes them on the workspace's App registrations page. It shows the addresses to give each app: the Redirect URI (a GitHub App's Callback URL), and GitHub's Webhook URL or Google's RISC receiver (optional), where the app says when access ends.
-
An app can tell the runtime when access ends, at the registration's
noticesUrl(POST /v1/connection-notices/{tenantId}/{appId}), which must be reachable from the internet; each notice is checked by its signature. Uninstalling the GitHub App removes its connections, and suspending it makes them need reconnecting until it's lifted. With Google's Cross-Account Protection, a person's withdrawn access or disabled account removes their connections at once, not at the next renewal (Notices from the app). -
An approval for a call with a person's connection is that person's alone to decide: they need a reviewer seat at its rank or above, or the call fails at once with
connection-approver-not-a-reviewer; add them on the Reviewers page. A tenant admin sees it but can't decide it (403 named-approver-required), and it never escalates: undecided at its deadline, it expires. The console shows the account under As, and the API hasapproverandconnection(Approvals). -
Connections are in the audit log, on legal hold: each connect and reconnect (
connection-created), removal (connection-removed), and app registration made or changed (connection-app-set) or removed (connection-app-removed). WithKINDGI_COMPLIANCE_CLASSIFIER=shipped, they're signed and kept as a secret's change is. An event names the account by a hash, not by its address (On legal hold). -
A LinkedIn connection needs reconnecting every 60 days: LinkedIn gives a self-serve app no refresh token, so the runtime marks the connection as needing reconnecting just before its access ends (
access-expired). A run its owner started then waits for them to connect again; any other run's call fails withconnection-missing(When LinkedIn ends access). -
Ready-made tools for Gmail, Outlook, GitHub and LinkedIn in
@kindgi/connections, each included under the id your pack names:gmailSend,gmailMessagesList,gmailMessageGet,gmailReply,outlookSend,outlookReply,outlookMessagesList,outlookMessageGet,githubIssuesList,githubLabelsList,githubIssuesAddLabelsandlinkedinPost. To write more,appFetchcalls an app's API with a call's connection, paced by the app's rate limits (Use a connection in a tool). A tool imports its connection names, such asConnectionRejectedError, from@kindgi/sdk/define, as it does its other names. -
Read and answer mail with the ready-made tools:
gmailMessagesListlists or searches a Gmail mailbox, newest first, andgmailMessageGetreads one message whole, in the same shape asoutlookMessageGet: its thread id, the first 20 people of each of To, Cc and Reply-To, its text and its first 20 attachments' names, types and sizes.gmailReplyandoutlookReplyanswer a mail in its thread, only to the one address the mail asks for, its Reply-To or else its From: a reply to any other address is refused, naming the right one, and nothing is sent. In a run no person started, a reply waits for a yes, as a send does. Each mail tool takesas: 'company'to use the company's mailbox, which a tenant admin connects by signing in as that mailbox; give such a tool its own id. A mail's text keeps where its links go, without their tracking parameters (Ready-made tools). -
A tool can say its results are text from outside:
resultIsOutsideData: true(result_is_outside_data=Truein Python,.resultIsOutsideData(true)in Java and Scala) says the tool's results are text nobody checked, such as a mail someone sent. An agent then reads each of its results as data, not instructions, in that turn and in every later one. It changes what the model is told, not what the tool may do.GET /v1/toolsshows it, and every ready-made mail read sets it (Results from outside). -
kindgi connectionsandkindgi connection-apps: connect, list and disconnect accounts from the terminal (kindgi connections), and register the company's apps, for tenant admins:add google,add github,add linkedinandadd microsoft --tenant=<directory>(oauth2.tenantin the API) (kindgi connection-apps).connectprints the link to open and, at a terminal, waits until the connect finishes.--quietprints the link alone. -
kindgi runs resumenames a connect the run waits for: the app, what it asks for and the link to connect from, with when the link stops working. It exits6when that's all the run waits for.kindgi runs getprints the same line, andruns.getanswers it underwaitingFor.connections(When the connection is missing). -
kindgi init --template=follow-up: an agent that writes a follow-up mail from your notes and sends it from your own Gmail, each send approved first. -
Connections in the API and the clients:
GET /v1/connection-entrieslists the apps a company can connect, with what each permission allows in plain words, the directory a registration signs in at, and what a disconnect withdraws at the app./v1/connection-appsregisters the company's apps, for tenant admins, and/v1/connectionsstarts a connect, lists connections and disconnects them. The TypeScript client has them asclient.connectionEntries,client.connectionAppsandclient.connections, and the Python client as the same resources (Connections reference). -
kindgi exports createexports connections: the tenant's app registrations (connection-apps.jsonl) and its connections (connections.jsonl), removed ones too. Neither holds a token, and a registration names its secrets by reference only (kindgi exports). -
@kindgi/connections-inmemory, for development and tests: an in-memory connection binding and resolver, with a fake app in place of Google's or GitHub's servers. A test connects without a browser, and hooks make the fake app refuse a code, fail a renewal, withdraw a grant or send a notice. It refusesNODE_ENV=productionunlessproductionSafe. -
The skills know connections: the tool-authoring skills (TypeScript, Python, Java and Scala) say how a tool declares the connection it needs, reads the call's token, and refuses with the connection's name when the app answers 401; the TypeScript one points at the ready-made tools and
appFetch. Thekindgi-usingskill knows an approval addressed to one person, and hands over the link to connect from when a run waits for a connect (kindgi runs resumeexits6). The TypeScript getting-started skill names the other provider presets, as the Python, Java and Scala ones do. -
Your coding agent can upgrade a self-hosted deployment: the getting-started skills (TypeScript, Python, Java and Scala) say how, and load for it. There's no migration script: the runtime brings its database up to date when it starts. A small dev deployment on Cloud Run, on runtime 0.1.8 or later, upgrades with the module's
./upgrade.sh,--dry-runfirst: its plan takes every*.auto.tfvars.jsonin the module's folder, the pack's env among them, andyesapplies exactly the plan it showed. Any other Cloud Run deployment upgrades by hand, staging first (Upgrade by hand). One on Azure Container Apps follows its page's "Operate it" section, and any other the upgrade steps in Operate a self-hosted runtime (Your coding agent). -
The Cloud Run
upgrade.shtakes--dry-run: it lists every change a real run would make, in order, and shows Terraform's plan for the new image, but changes nothing and never asks foryes. It doesn't run the upgrade checks against the database, since they run as jobs in your project (Operate it). -
The Cloud Run
upgrade.shtakes a server-only release: a release such as 0.2.0.1 is a server fix for 0.2.0, with no@kindgi/sdk@tag of its own. Use theupgrade.shas of the@kindgi/sdk@0.2.0tag, with--to 0.2.0.1(Operate it). -
A run says whom it acts for:
actsFor,user:<id>orservice_account:<id>, onGET /v1/runsandGET /v1/runs/{runId}, and in the TypeScript, Python and Java clients'Run. It's recorded when the run is created and never changes: a schedule's or a webhook's run acts for the trigger's owner, and a child run for its parent's. A public run token's view and therun.finishedwebhook don't carry it. -
Your own links in the console:
KINDGI_CONSOLE_LINKS, a JSON object of label to URL, shows up to 8 links, such as your help desk, status page or data processing terms, on every page of the console, the sign-in page too (Your own links in the console). -
The runtime can check its database server's certificate against a CA you give:
KINDGI_DATABASE_SERVER_CA_PATH, a PEM file, orKINDGI_DATABASE_SERVER_CA, the certificates inline (runtime 0.2.0 or later). Every connection then uses TLS, and the certificate must chain to one of these CAs and be in date. It's for a database reached by an address its certificate doesn't name, such as Cloud SQL by private IP. OpenFGA's own connection to the database has a section of its own (Check the database's certificate). -
A hard revoke says until when your secret manager keeps a recoverable copy: Azure Key Vault keeps a deleted secret it can't purge for the vault's retention period.
DELETE /v1/secrets/{name}?hard=trueanswersrecoverableUntil, thesecret-hard-revokedrecord carries it, andkindgi secrets revoke --hardprints it. Setting the name again before then purges that copy if Kindgi now can (Revoking for good). -
kindgi license enroll,kindgi license renewandkindgi initin an existing app follow--json,--raw,--tableand--quiet:enroll --quietprints the enroll line alone, the one you add at access.kindgi.com, andrenew --jsongives the key'sexpiresAtanddaysLeft. With none of these flags, all three print what they printed before. -
An agent's tool-call check is told the tool's version:
authorizeToolCallgetstoolVersionwithtoolId, before the call and once an approval comes back, so an authorizer can apply a rule per version. It's optional, so an authorizer written without it keeps working. -
Set how much each Gemini model thinks: a Gemini provider's
adapter_config.thinkingLevels, asmodel=levelpairs ("gemini-3.8-flash=low"), orthinkingLevelsin code, sends one of Google's four levels,minimal,low,mediumorhigh, on every call to that model. Gemini 3.8 Flash thinks on every call, and its thinking bills as output and counts againstmaxOutputTokens. A model it doesn't name thinks as Google sets. An entry that doesn't hold up, such as a level below the least the model takes (minimalon Gemini 3.8 Flash), is refused when the provider registers (Make it think less). -
A shared trigger can run as its project:
--run-as=project(runAsProject: truein the API) on a schedule, webhook trigger or mail trigger makes its runs act as the project's own service account, made the first time with the editor role on the project. It takes a project admin. The account has no keys, its role can't be changed and it can't be named by id, and a trigger'sownersaysisProjectAccount: true. A tenant admin may unregister it, which stops its triggers until an admin takes each over, and deleting the project unregisters it (A project's own account).
-
A turn whose
maxStepsis above 32 stops at its 32nd model call: a turn makes at most 32 model calls, one per pass of its loop. With a highermaxSteps, a model that still wanted a tool on the 32nd call ended the turn with no answer, and the failure didn't name the budget. The turn now fails withbudget-exceeded, kindstepsandlimit32 (When a turn runs out), and a typed answer that doesn't fit on that call fails it withoutput-schema-violation. AmaxStepsof 32 or less works as before.defineAgent's doc comment now gives the real defaults: 8 steps, no cost cap and 120 000 ms. -
kindgi buildandkindgi deployprint each line as it happens: the build server's log as the server sends it, Docker's forkindgi build --local, and, for a deploy, the wait for a hosted pack service. They used to print nothing until they were over. A build or a deploy that fails keeps what it printed, with the error after it; a build server's build that failed, or a deploy that stopped before it was sent, used to print only the error. The summary still goes to stdout at the end. -
--quietprints errors and warnings only, the same way in each command:kindgi deploy --quietused to print all of deploy's own lines, andkindgi build,kindgi devandkindgi exports createleft out their warnings or printed their progress. Each now keeps its errors and warnings, the CLI pin's warning and a rate limit's wait among them, and leaves out the rest.kindgi dev --quietshows log records fromwarnup, not onlyerror, and still says when the framework skills are out of date or couldn't be refreshed. About twenty more commands that still printed what they'd done,secrets,env,key,init,mcp,webhooks,sites,upgradeandauth registryamong them, now leave it out, and a failedkindgi runs startrun's warnings and error now show. What's shown only once prints alone on stdout under--quiet, askindgi connections connect's link does:kindgi tokens create's secret, which it used to print nowhere,kindgi webhooks register's signing secret, andkindgi sites' one-time code. -
The 90-day limit is a preview release's, whatever its version: the runtime's refusal and startup warning,
kindgi dev's warning, the console's license line and the description ofGET /v1/license'spreviewno longer say that it ends at Kindgi 1.0. A release still stops starting 90 days after it was released, with a warning from 30 days before, unless a production key exempts it. -
The Cloud Run
upgrade.shwaits for a new backup-bucket grant: when the grant it makes on the backup bucket is new, the database export no longer stops with HTTPError 412 while the grant takes effect. It tries again every 15 seconds, for up to 7 minutes. If Cloud SQL still can't write to the bucket after that, it stops before changing the deployment and says how to check the grant. -
kindgi improveandkindgi evalname the command you meant:kindgi proposals improve, andkindgi eval-runsorkindgi eval-suites, where they printed only "Unknown command". An unknown command named like a JavaScript object's member, such asconstructor, printed aTypeError; it now gets the usual message. -
kindgi deploy --dry-runworks on an unsigned build (kindgi build --skip-sign): it shows the body it would send, less the signature's fields, and exits 0. It used to fail with "Internal error building POST body". Without--dry-run, an unsigned build is refused as before. -
A TypeScript pack that installs with pnpm or Yarn no longer starts with a warning that its pack service dropped
COREPACK_ENABLE_DOWNLOAD_PROMPT. Rebuild the pack's image with this CLI to stop it; nothing else in the image changes. -
kindgi build --hosted's link for a pack over 30 MiB goes to the docs for the CLI's release line, not always to 0.1's. -
kindgi initin an sbt app readsnameandversioninside a one-line.settings(…), such aslazy val root = (project in file(".")).settings(name := "acme-ledger", version := "1.2.0"). It used to stop unless--pack-idwas given, and to use0.1.0for the version. A setting inside a comment is no longer read. -
A schema with a format bound compiles under
HOSTED_BOUNDS, as underSELF_HOSTED_BOUNDS:formatMinimum,formatMaximumand their exclusive forms, ondate,timeanddate-timevalues. In strict mode such a schema was refused for an unknown keyword, and otherwise its bound was ignored. -
kindgi key create <id> --env <name>'s note follows what the environment has: it reads thekindgi.config.tsin the folder it runs in. When the environment already names this key (itssigningKeyis this key's file, and itssignerKeyIdis this key's id or unset), the note sayskindgi build --env=<name>will sign with it, and there are no lines to add. Before, it always said to addsigningKeyandsignerKeyId. When the environment names another key, the note shows the two fields it has now, then the lines to add. With--home <dir>, thesigningKeyto add is the file the key went to: its path from~when that's under$HOME, such as'~/work/.kindgi/keys/<id>.pem'for--home ~/work, and its full path otherwise. It was always'~/.kindgi/keys/<id>.pem', wherekindgi buildfound no key. The note's lines are written askindgi.config.tsstrings, so a quote or a backslash in a path is escaped (Rotate a signing key). -
A tool's error says why it failed: in TypeScript, a tool whose fetch failed used to report only
fetch failed. The message now names up to three causes, as Node does (TypeError: fetch failed; caused by ConnectTimeoutError [UND_ERR_CONNECT_TIMEOUT]: …), and a refused connection names the addresses it tried. It shows wherever the failure does: the run's record and events, the console, the model's retry and the CLI, for a pack tool's handler, a check'sevaluate, a pack file that fails to import and a tool run in the server's own process. An error with no cause reads as it did (When a call fails). -
A trigger can't be set to run as an owner that can't run what it starts: with an authorization store, naming a service account (
--run-as), running a trigger as its project, taking one over, or changing a schedule's or mail trigger's agent or flow is refused with409 trigger-owner-cannot-run-targetwhen the owner can't run it, and nothing changes. The message says what fixes it, such as giving the account the editor role on the target's project. Before, the change was accepted, and then every fire was refused until the trigger paused (Run as a service account). -
With authorization on, a change answers once its own access is written, even behind a queue of older changes: creating a project, publishing an agent or adding a member wrote one batch of up to 500 queued authorization changes before answering. With more of the tenant's older changes waiting, it could answer before its own were written, and the caller's next request could get
403 permission-denieduntil the background worker caught up. It now keeps writing until its own are in, for at most 2 seconds; a slower write lets the answer go first, and the background worker finishes it. -
A tenant's setup that fails after making its OpenFGA store deletes that store: when writing the store's model, the tenant's first grants or the runtime's record of the store failed, the store stayed in OpenFGA with nothing naming it, and each retry made another. The setup now deletes it, unless the record of it may have been written, and names a store it can't delete, or keeps, in its error. A store left by a runtime that stopped during the setup stays in OpenFGA.
-
A flow step that waits inside a loop nested in another loop suspends the run: such as an agent step whose tool call waits for a person's yes, in the body of a
loopstep that is itself in another's body. Before, the run failed at once withInterrupted: the run's executor stopped …, and answering the wait couldn't resume it. Now the run waits, and goes on where it waited. -
A block a turn can't load answers
422, not500:block-unresolvable, for no version of a data block in the agent's range, a pinned version that's gone, the wrong kind, or no blocks on the runtime, answered500, as if the server had failed. It answers422now, astool-version-unresolvabledoes. The TypeScript and Python clients still raise it as aServerErrorwith itscode. -
The runtime says when two MCP endpoints hold the same tool id: endpoint
alistingb.cand endpointa.blistingcboth makea.b.c. Each sync skipped such an id without a word, and a reference got whichever version its range picked. The log now warnsMCP tool id <id> is held by more than one endpoint at once, naming each endpoint and its versions, and the runtime's start lines have a⚠ MCP:line with how many. Unregister the versions of all but one endpoint (When a tool id is taken). -
A deployment with no tool and no check of its own gets no pack service on a runtime that serves many tenants (
KINDGI_PACK_ROUTING=per-deployment): its answer has noendpoint. Before, it got an endpoint that stayedpending, though the deployment was in place. One left pending by an earlier runtime is no longer shown (Serve many tenants). -
A trigger's owner records are on legal hold, as a service account's are: with
KINDGI_COMPLIANCE_CLASSIFIER=shipped,trigger-owner-set(a trigger made to run as a service account, or taken over) andtrigger-changed-for-owner(a project admin's change to a trigger a person owns) are kept for good, signed and exportable. Before,trigger-owner-sethad no policy: it was kept, but left out of the compliance evidence and of signed exports. Records from before the upgrade join the compliance evidence and signed exports at the upgraded runtime's first start. A classifier file of your own needs both kinds added (On legal hold). -
On a runtime without an authorization store, the People list says everyone works in every project: each person's Access reads "Every project (this runtime doesn't check roles)", then any reviewer role, where it read "no role yet" for someone without one. With a store, it reads as before (Without authorization).
-
On the console's sign-in page, only the button you clicked says it's busy: clicking Continue also turned Sign in with an API token into "Signing in…", clicking that turned Continue into "Continuing…", and Sign in as seeded user and an emailed link's Continue as … did the same. The others now keep their labels, disabled until it's done, and coming back with the browser's Back button no longer shows the page still busy.
-
Screen readers read console labels they used to skip: a run's step status icons, the release gate's checks when you pin a version, Add a person's outcome marks, a new API key's secret, the guardrail page's What it caught and each rule's trend card, and, when you set up a second factor, the key to type in if the authenticator app can't scan the QR code ("The key, to type in"). A rule's preview is read out as its answer changes. Nothing changes on screen.
-
The console and the runtime's root page link the docs of their own release line, such as
https://docs.kindgi.com/v0.2/for 0.2.0 and its candidates. The console's Docs links went to the 0.1 docs whatever its version, and Add an identity provider's Step by step went to its guide in the unversioned docs. The root page's Documentation link (GET /) went tohttps://docs.kindgi.com/, which follows the newest release. -
An Improve schedule counts only the corrections on the version an Improve run would start from: the version pinned for its scope, else the latest. Before, an older version's corrections kept counting, so a schedule could start Improve runs for mistakes a newer version had already fixed (Improve on a schedule).
-
An interrupted Improve run ends as its evaluation says when it's picked up again: one whose best change beat the recorded answers ends
proposed, even if its suggested change was meanwhile sent for review, pinned or withdrawn. Before, it endednothing-found, hiding a change waiting for a reviewer, and a run whose best change didn't beat them gave the reason "The hold-out comparison ended withdrawn." -
The console says what pinning a suggested change will do: Ask to pin it restates the result and the release gate policy's verdict, or says "No release gate policy covers this scope", where it said the version "goes through the scope's gate" even with none. When Improve needs a version pinned for every project first, it links to The agent's pinned versions, and deriving a version warns when none is pinned in the project, since its runs take the new one at once.
-
A Python tool or agent whose model has a pydantic tagged union deploys: with
Field(discriminator=...), pydantic writes OpenAPI'sdiscriminatorbeside the union'soneOf, and the runtime refused the tool's input or output, or the agent's typed answer, withstrict mode: unknown keyword: "discriminator". The SDK now leaves it out, each member's tag aconst(anenumfor several values) andrequired. A union that a callableDiscriminatorpicks is sent as ananyOf, so a value that fits two members, which pydantic takes, is no longer refused.
Changed
Section titled “Changed”-
kindgi dev's banners no longer print the dev token in full: theTokenline of the "Kindgi is up" block, and--no-watch'sBearer tokenline, show it askgi_bt_…and its last four characters, as the runtime's own startup line does, so a pasted dev log doesn't give a working token away. Each line says where the full token is:tokenin the pack's.kindgirc.json, with the API's URL asapiUrl(Connect your app to the runtime), or.kindgi/dev/runtime.envif that file can't be written. A token pinned with--dev-tokenin another shape shows only its last four characters.--jsonand--rawstill print the token in full. The TypeScript and Python getting-started skills say where the token is too. -
The runtime image moves from
quay.iotoregistry.kindgi.com. access.kindgi.com no longer gives a robot name and token for quay.io: you log in with your license key instead (Log in to the registry). -
kindgi auth registrylogs in toregistry.kindgi.comwith your license key: the username there iskindgi, so it needs no--username, and the hidden prompt asks for the license key. A value that isn't a license key (one starts withkgi_lk_) is refused before anything logs in, and isn't shown. The hints inkindgi auth registry,kindgi devandkindgi doctorname the license key, not a robot, when the image is onregistry.kindgi.com. Another registry, such as a mirror, still takes--usernameand its own token. -
A schedule or a webhook trigger is personal or shared, and its owner stays put. One a person owns is personal: its runs act as them, with their connections, and only they or a project admin can change, pause, resume, fire or delete it. Anyone else is answered
403 permission-denied. One a service account owns is shared: its runs act as the account, with the company's connections. Changing what it runs (its agent or flow and version, its input, its tools allowed unattended, a webhook's signing secret) takes a project admin, and the project's writers can still change the rest, and pause, resume, fire or delete it. No change moves the owner: only a take-over does. A change to a personal trigger by anyone but its owner is recorded astrigger-changed-for-owner. Without an authorization store, a project admin here is a tenant-admin key (Shared or personal). -
An Improve run counts everyone's corrections until there's a restricted judge class: with no
classWeights, an Improve run and an Improve schedule count every correction, each by its class's weight (as-recorded), until the test cases' project, its tenant, or the agent improved there has a restricted judge class. Then they count only the corrections under one (restricted-only), as before. A schedule decides at each run. One created before 0.2.0 kept an explicitrestricted-only: recreate it withoutclassWeightsto follow the project (Whose corrections it learns from). -
An Improve run's cost counts the runs that prove its best candidate, on the cases it didn't search, and the current version's replays there. They run after the search, so they can take an Improve run past
--max-cost, and an Improve schedule can reach its monthly cap sooner (Start an Improve run). -
A suggested change Improve drafted needs someone else to approve it when there's another reviewer: with a second reviewer who could decide it, the person who asked to make it live can't approve it (
403 separate-approver-required). A lone reviewer still can. A release gate policy's ownseparateApproverstays the floor (Start an Improve run). -
An Improve run you start asks for its suggested change's review itself, as a scheduled one does, in the name of whoever started it. While another reviewer could decide it, the person who started the run can't approve it (
403 separate-approver-required). Before, its change waited until someone asked for the review, withkindgi proposals requestor the console's Request promotion. -
The release gate's messages use the product's words: "The release gate policy refused …", "the test run", "this version" and "the live version", and experts' judgments. Its replay checks say "N tool calls were refused", not writes, since a refused call can be a read, and in the console a policy's Refused writes is Refused tool calls. The error codes, check names, fields and counts don't change.
-
The console's Improve and evals pages, and Improve's reasons, use plain words: Test sets is now Test cases, the Quality tabs Queue and Proposals are To correct and Suggested changes, a policy's Tool rules are Approval rules, Judge this run is Correct this run, and the Trends tab says Marked right where it said Yes. An Improve run's
outcome.reasonand a suggested change'shypothesissay "the cases Improve learned from" or "didn't learn from", not the search or hold-out part, and a schedule's skip note counts experts' corrections, not trusted judgments. Routes, API fields and error codes don't change. -
An Improve run's page says why it found nothing, and when to doubt it: Nothing measured when nothing it tried could be scored, else Nothing clearly better, and where it stopped: at the limit on changes to try, on the cost budget, or with no further change to try. With fewer than 10 test cases picked, the Improve dialog says the figures may not hold, and a suggested change checked on fewer says to read them with care. A suggested change's status reads, for example, Better on the test cases, and a block's page marks what Improve may change Tunable.
-
A conversation you can't read answers
404 conversation-not-found, as if it didn't exist, where it answered403: reading it or its messages, closing or unregistering it, and starting a run in it that its participant rule refuses. A caller who can read it keeps the403, and the clients raise the not-found error in place of the forbidden one (Hold a conversation). -
A hard revoke is no longer called "cryptographic erasure": it erases the value at Kindgi and hard-deletes it in a secret manager, and can't be undone, but backups and a secret manager's own retention may keep copies for a time (Revoking for good).
-
kindgi devrefreshes the pack's framework skills as it starts, after an upgrade, where it only said they were behind. It works askindgi skills syncdoes without--force: skills you edited are kept, and one you deleted stays deleted. -
The
woocommercetemplate's store agent takes its instructions from a prompt block the pack brings (blocks/store-agent-prompt.liquid), sokindgi deploypublishes it with the agent, and an Improve run on the instructions can draft new ones. A change to them takes a new version within the agent's range. -
The pages a person opens from a link are in the sign-in page's frame: a link to connect an app, the page the app sends them back to, an approval's link (
/console/approvals/<approval-id>), and signing out. They show Kindgi's band beside what the page says, with links to kindgi.com and the docs, the deployment's terms and privacy links when they're set, and its own links under the page (Terms and privacy links). -
The console has its own pages for an error and for an address with no page: "This page couldn't be shown", with Reload and Open the console, and "Page not found". On a page with the console's menus, they show in its place and the menus stay. Without the menus, such as at sign-in or on a link to connect an app, they're in the sign-in page's frame, with the deployment's terms and privacy links when they're set (Terms and privacy links). The error page doesn't show the error itself; the browser's console has it.
-
The Cloud Run and Azure Container Apps modules ask the pack's service whether it's ready every 2 s as it starts, where they asked every 5 s, still for up to two minutes in all. On Cloud Run, a cold start's first tool call waits about 1 s for it, not about 2.5 s. It takes effect at your next
terraform applywith the updated module (Cloud Run, Azure Container Apps). -
On Cloud Run, the pack's service has CPU only while a call runs, so the instance
pack_min_instanceskeeps up bills at Cloud Run's lower idle rate between calls, and its CPU is boosted as it starts. It takes effect at your nextterraform applywith the updated module (Cloud Run). -
approvals.completeTokenis gone from@kindgi/client, with itsCompleteTokenInput, which@kindgi/sdkre-exported too. It had no route and always threwnot-yet-wired. Code that importsCompleteTokenInputstops compiling; an approval's run resumes throughapprovals.decide. -
A deploy that changes a tool but keeps its version is refused:
409 tool-already-registered, naming the fields that differ, and nothing is deployed. Before, the deploy answered ok, kept the definition the version was first published with, and ran the new code under it, so a new input schema,mutatingor approval didn't take. Give the tool a new version. A new image of the same tool still deploys. Deploying again an image recorded before 0.2.0, whose tool the runtime kept with another definition, now gets the 409 too: give the tool a new version and build again (Deploys make the new version for you). -
In TypeScript,
InvokeAgentErrordeclares every error an agent turn returns:run-journal-unavailable,hitl-rejected,hitl-cancelledandhitl-withdrawnare now in the type, with their error classes, so aswitchoncodesees each. The codes and messages are unchanged. Aswitchthat checks every case (withneveror anassertNever) must now handle these four to compile.resumeAgentTurn'sagent-version-mismatchnow carriesconversationId(Decisions). -
The emails the runtime sends are in Kindgi's brand: the sign-in link, an invitation, the notice that a recovery code was used or a second factor removed, and the reviewer email and its digest have an HTML part with the Kindgi band. An email with one link (a sign-in, an invitation, one approval) has it as a button, written out under it, and a digest links each approval as Open it. They load no image or font, so opening one contacts no server. Subjects and text parts are as before. An email whose HTML part can't be made goes as text only, and the runtime logs a warning (Reviewer email).
-
A project's dashboard says whether it's live, and what's deployed: the Production card is now a button in the header, Testing mode or Live, that says what that means and holds a tenant admin's Go live or Move back to testing. The Kindgi Core card names the pack and version deployed, or "No pack deployed to this project", and how many values aren't ready. Renaming the project keeps its slug unless you tick Change its slug too.
-
The console says Latest or Pinned for an agent's versions, not live: an agent's Live versions page is Pinned versions, at
…/agents/<agent>/pinnedwhere it was…/live, with Where it's pinned and Pin history, and a suggested change's Request promotion is Ask to pin it. "Live" is kept for a project's mode. The API, the CLI and the docs still call a pinned version live. -
An agent's, a flow's and a tool's pages show what each does: an agent's page is about the version this project's runs use, with its Input and its Available tools, marked Only reads and Needs approval. A flow's Steps diagram zooms, goes full screen and opens each step's agent, tool or flow. A tool's page lists its Input and Output fields, Used by agents and Used in flows. Register agent and Register tool are hidden: an empty list says to deploy the pack, or, under
kindgi dev, which folder. -
A run's page folds a guardrail's reason: the reason can quote what the guardrail blocked, such as a card number, and the run's failure and a flow step's error printed it in full. "A guardrail blocked the answer.", the guardrail and the code stay in view, and the reason is behind Show why it was blocked, as the blocked answer is behind Show what was blocked. The run's journal keeps it in each row's folded details.
-
The runtime starts faster when its database is busy: its migration check at each start sends about half the statements it did when there's nothing to apply. Each table's row security, policies and grants are still checked at every start.
-
A Python tool's schemas are checked when it's defined, as the runtime compiles them:
@toolandhttp_toolraiseDefinitionError, in the runtime's words, for an input or output schema, a dict or one derived from a model or a type, that the runtime would refuse: a keywordjson_schema_extraadds, aformatit doesn't know (pydantic's"format": "path"for apathlib.Pathfield),minLengthwith no"type": "string", or apatternJavaScript'sRegExpdoesn't read, such as(?P<name>…).@toolrefuses the same in a schema underneeds_spec.envorneeds_spec.secrets, and an env default that isn't a string. Before, the deploy refused it (Write a tool). -
kindgi buildrefuses a Java or Scala tool's schema where the runtime would: beyond unknown keywords, a keyword with notypeit applies to (minLengthwith no"type": "string"), atypeits context can't be, arequiredproperty nothing defines, an emptyenum, a$refthat only leads back to itself, and apatternthe runtime's JavaScriptRegExprefuses. Before, such a schema reached the runtime, which refused it, and a pattern went by Java'sPattern, so(?i)abcpassed the build. The indexer refuses the same in a schema underneedsSpec.envorneedsSpec.secrets, and an env default that isn't a string (Write a tool).
Known issues
Section titled “Known issues”-
Set
KINDGI_SEED_USER_IDin lower case. With an upper-case UUID (macOS'suuidgenprints one), the seed user's grants show no projects, teams or reviewer role, an approval addressed to it can't be decided, and it can approve its own requests where a second person's approval is required. To tell: the people list shows the seed user in upper case, and project and team member lists show it in lower case. To fix it, set the value in lower case and restart the runtime. That makes a new seed user with the lower-case id, a tenant admin; the old one keeps its keys, so mint new ones for the new seed user (People, API keys and service accounts). -
Set
KINDGI_TENANT_IDin lower case when you set up a new runtime. With an upper-case one (macOS'suuidgenprints one), parts of the runtime read the tenant as two, so some checks miss it: sign-in on a domain with its own identity provider, ending console sessions when the API token changes, and a retention purge or an erasure of files kept with a run. 0.3.0 fixes these checks. Until then, manage the tenant one way only. If its people sign in through its own identity provider, register the provider and manage the people with the API token as the bearer of your CLI or API calls, not in the console or with an API key. Otherwise use either way, but not both. Keep the id of a runtime that's already running as it is, even in upper case, including when you upgrade. -
Use ids in lower case when you remove or change access through the API. With an authorization store, removing or changing a project or team membership, a team's grant on a project, or a service account's grant with an id that isn't in lower case can leave the access in place, though the change shows as made. Use ids as the API returns them, in lower case. To take away access left this way, give it back as it was, with the ids in lower case, and then make the change again. Fixed in 0.3.0 (People, API keys and service accounts).
-
Set
KINDGI_PUBLIC_URLon a server behind a proxy, in Docker Compose too. A Compose file that serves the runtime on your domain through a proxy doesn't give the server its public address unless you add it. Without it, a paused tool call's link is made from the address the server binds, which the other system can't reach, so its answer doesn't arrive and the run waits until the wait times out. The server logs a warning the first time it makes such a link. AddKINDGI_PUBLIC_URL: https://<your domain>to the server'senvironmentin the Compose file, or, on a runtime set up as Self-host Kindgi shows,KINDGI_PUBLIC_URL=https://<your domain>to itskindgi.env, and restart the server (Wait for another system). -
Keep a paused call's link out of a pack tool's errors. A failing pack tool's error is cleared of the call's secrets and connection tokens, but not of the link a pausing tool is given, so an error that repeats it keeps it where the run's errors are read. The link stops working when the call fails. Write such a tool's errors without the link. Fixed in 0.3.0 (Wait for another system).
-
Save a stored file rather than opening its download in a browser. A browser that opens an artifact's download can show the stored file as a page of the runtime's own address, where the console is signed in. Download files with
kindgi artifacts download, which saves each one to a file. If a proxy fronts the runtime, it can addContent-Disposition: attachment,X-Content-Type-Options: nosniffandContent-Security-Policy: default-src 'none'; sandboxto the responses whose path starts with/v1/artifacts/. Fixed in 0.3.0 (Keep files with a run).
Upgrade steps
Section titled “Upgrade steps”-
From a 0.2.0 release candidate: 0.2.0 is 0.2.0-rc.1's code. From rc.1, no migration applies, and only the version changes: its 90 days as a preview release count from 0.2.0's release. From rc.0, the first start applies the two of the seven migrations below that rc.1 added, which take a short lock on
kernel_runs,kernel_triggers,kernel_trigger_firesandservice_accounts, so back up first, as for any upgrade. -
Log in to
registry.kindgi.combefore you pull 0.2.0, on every self-host path:docker login registry.kindgi.com --username kindgiasks for your license key. The Cloud Run and Azure Container Apps pages copy the image into your own registry from there (Pull the runtime image).kindgi devpulls its runtime from there too: on each machine that runs it,kindgi auth registrylogs in. -
A small dev deployment on Cloud Run (the module with
network_mode = "none", at 0.1.8 or later): run the module'supgrade.shas of the@kindgi/sdk@0.2.0tag, since 0.1.10's copy goes to 0.1.10 by default, from the old registry. It copies the runtime fromregistry.kindgi.com, so log in there before you run it. Its plan also changes the pack's service in place, with or without--pack-dir(its CPU and its readiness checks, under Changed). For an earlier release than 0.2.0, use the script as of the@kindgi/sdk@0.1.10tag. -
Set the public URL if it isn't set (
KINDGI_PUBLIC_URL; on Cloud Run and Azure Container Apps,public_url, empty by default), to the URL people open the console at: once it's set, the console's sessions are accepted from that origin only. A paused tool call's link is made from it. Without it, the link is made from the address the server is bound to, which another system can't reach, and the server logs that at the first pause. Connections stay off until it's set, and the server logs what else they need as it starts. Each app's sign-in sends people back to<public URL>/console/connect/callback. -
Without an authorization store, check who changes the tenant's settings: a script or a person that isn't a tenant admin there now gets
403 permission-deniedwhen it changes them, and on any call to the outgoing webhook endpoints or the compliance evidence. Use the deployment's API token or anadminkey (Security fixes says who's a tenant admin there). -
Seven new migrations, all additive: new tables, and new columns that can be empty, with nothing rewritten, among them the one that keeps the waits of paused tool calls. The first start runs them in seconds, as it runs any other migration. Five of them take a short lock on
kernel_runs,kernel_triggers,kernel_trigger_fires,hitl_approvals,judgmentsorservice_accounts; the other two only add tables. A long transaction holding one of those tables makes the start stop after about a minute, naming the session that holds it. End that session or let it finish, then start again; on Cloud Run, the old revision serves meanwhile. -
A pack built for 0.1.10 keeps working without a rebuild. To use 0.2.0's features in it, such as a tool that pauses, a connection or data blocks, move its pins to 0.2.0 first. A Python pack made by a 0.1 CLI pins
kindgi>=0.1,<0.2andkindgi-cli>=0.1,<0.2:uv add "kindgi==0.2.0"anduv add --dev "kindgi-cli==0.2.0". A TypeScript pack takespnpm add @kindgi/sdk@0.2.0andpnpm add -D @kindgi/cli@0.2.0, and a Java or Scala pack./kindgiw upgrade --to=0.2.0. Upgrade the runtime before you deploy a pack with blocks:kindgi deployrefuses it on a runtime that doesn't publish them. -
On Azure Container Apps, the plan refuses a
KINDGI_TENANCYorKINDGI_PACK_ROUTINGother thansingleinserver_env, and either one inserver_secret_env: the module runs one tenant, and the server wouldn't start with them there. -
With Cloud SQL by private IP, the Cloud Run module now gives the runtime the instance's CAs (
KINDGI_DATABASE_SERVER_CA), so from then on, rotate the server's CA in this order: add the new CA, apply, then rotate (Rotate the server's CA).