<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>AI-Git-Bot — News</title>
  <subtitle>Release notes, product news and engineering write-ups for AI-Git-Bot.</subtitle>
  <link href="https://gitbot.eu/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://gitbot.eu/articles/" rel="alternate" type="text/html"/>
  <id>https://gitbot.eu/articles/</id>
  <updated>2026-11-11T00:00:00.000Z</updated>
  <author>
    <name>Tom Seidel</name>
    <email>tom.seidel@remus-software.org</email>
  </author>
  <entry>
    <title>One key, many models: OpenRouter in AI-Git-Bot</title>
    <link href="https://gitbot.eu/articles/openrouter-with-ai-git-bot/" rel="alternate" type="text/html"/>
    <id>https://gitbot.eu/articles/openrouter-with-ai-git-bot/</id>
    <published>2026-11-11T00:00:00.000Z</published>
    <updated>2026-11-11T00:00:00.000Z</updated>
<summary>A dedicated OpenRouter integration sends routing policy with every request: region choice for EU or US processing, zero data retention enforced per request, and an automatic router that picks a model per call. What the bot pins, what it refuses, and where the settings are.</summary>
    <content type="html">&lt;p&gt;AI-Git-Bot supports several AI providers, and OpenRouter is the one that is a router
rather than a model vendor. A single inference key opens a catalog of model families,
and the request carries policy with it: which region may process it, whether the
endpoint is allowed to retain it, and which parameters the endpoint has to support.&lt;/p&gt;
&lt;p&gt;The dedicated &lt;strong&gt;OpenRouter&lt;/strong&gt; provider type is not the same thing as pointing the
generic &lt;strong&gt;OpenAI&lt;/strong&gt; integration at &lt;code&gt;openrouter.ai&lt;/code&gt;. The generic path speaks plain
OpenAI and hopes the gateway behaves; the dedicated one speaks OpenRouter’s own
dialect, sends a routing policy on every call, and validates the key before it saves
anything. This article covers that integration: the setup, the routing and privacy
section, what automatic model routing can and cannot do inside the bot, and where to
watch the spend. The reference documentation:
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/blob/main/doc/USER_GUIDE.md#openrouter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;USER_GUIDE&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-put-a-router-in-front-of-a-review-bot&quot; tabindex=&quot;-1&quot;&gt;Why put a router in front of a review bot &lt;a class=&quot;header-anchor&quot; href=&quot;#why-put-a-router-in-front-of-a-review-bot&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The reason is not “more models”. It is that the same account serves every bot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One key, several families.&lt;/strong&gt; A review bot on a frontier model, a triage bot on a
cheap one and a coding agent on whatever is strongest for tool calls can all point at
one integration — or at several integrations with the same key and different model IDs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model choice is a text field.&lt;/strong&gt; Switching the model of a bot is an edit to the
integration, not a new vendor contract, and the suggested IDs in the dropdown are
examples rather than a catalog. Type any &lt;code&gt;author/model&lt;/code&gt; ID.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spend in one place.&lt;/strong&gt; OpenRouter credits pay for everything, and the per-integration
token log in AI-Git-Bot lines up with the activity view on the OpenRouter side.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data policy as configuration.&lt;/strong&gt; Region and retention are properties of the request,
so a bot reviewing a customer repository can be stricter than the bot reviewing your
own.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point is the part that matters in regulated repositories, and it is the part
the bot actually enforces instead of passing along.&lt;/p&gt;
&lt;h2 id=&quot;setting-up-the-integration&quot; tabindex=&quot;-1&quot;&gt;Setting up the integration &lt;a class=&quot;header-anchor&quot; href=&quot;#setting-up-the-integration&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AI Integrations → New.&lt;/strong&gt; Set &lt;strong&gt;Provider Type&lt;/strong&gt; to &lt;code&gt;OpenRouter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API Key&lt;/strong&gt; — an inference key. On save the server calls &lt;code&gt;/v1/key&lt;/code&gt; on the selected
official host, rejects management and provisioning keys, and checks that the key is
allowed in the selected region. A key that fails the check is not stored.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Routing and privacy&lt;/strong&gt; — region, data collection and ZDR, described below.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; — a concrete ID such as &lt;code&gt;deepseek/deepseek-v4.1-flash&lt;/code&gt;, or one of the
routers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Max Tokens&lt;/strong&gt; and &lt;strong&gt;Context Window&lt;/strong&gt; — the response limit and the model’s real
window. OpenRouter passes both through to whichever endpoint serves the request, so
a wrong context window is compounded by a router you did not pick.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable native tool calling&lt;/strong&gt; — on for models that call tools reliably. With it off,
the bot describes the tools in the prompt and parses a JSON answer.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/openrouter-with-ai-git-bot/openrouter-integration.png&quot; alt=&quot;OpenRouter integration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1229&quot; height=&quot;731&quot;&gt;&lt;figcaption&gt;The OpenRouter provider type with the Routing and privacy section: region, provider data collection and the ZDR checkbox.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;strong&gt;API URL&lt;/strong&gt; field is not editable for this provider — it is derived from the region
and shown as plain text, so the host and the policy cannot drift apart. A gateway of
your own in front of OpenRouter is a different situation: use the generic &lt;strong&gt;OpenAI&lt;/strong&gt;
provider for that, because a custom root would break the region check.&lt;/p&gt;
&lt;h2 id=&quot;automatic-model-routing&quot; tabindex=&quot;-1&quot;&gt;Automatic model routing &lt;a class=&quot;header-anchor&quot; href=&quot;#automatic-model-routing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;OpenRouter’s routers are model IDs. &lt;code&gt;openrouter/auto&lt;/code&gt; rates each request and picks both
a model and a reasoning effort for it; &lt;code&gt;openrouter/auto-code&lt;/code&gt; runs on the same engine
with a policy tuned for coding agents and harnesses. Enter either in the &lt;strong&gt;Model&lt;/strong&gt; field
like any other ID and the bot sends it unchanged.&lt;/p&gt;
&lt;div class=&quot;mermaid&quot;&gt;flowchart LR
  A[Request] --&amp;gt; B[Rate task]
  B --&amp;gt; C[Narrow pool]
  C --&amp;gt; D[Pick model]
  D --&amp;gt; E[Endpoint]
&lt;/div&gt;
&lt;p&gt;The pool in step two is where the bot’s settings become visible. The router only
considers models that the account’s guardrails, the ZDR requirement, provider
restrictions and your BYOK keys allow — so turning ZDR on narrows the router as much as
it narrows a pinned model. What the router cannot read is per-request router settings:
&lt;code&gt;allowed_models&lt;/code&gt;, &lt;code&gt;excluded_models&lt;/code&gt; and &lt;code&gt;cost_tier&lt;/code&gt; travel in a plugin block, and the bot
disables plugin overrides on every request. Sets that have to be request-specific belong
on the account or in a guardrail.&lt;/p&gt;
&lt;p&gt;There is a trade-off worth naming. Routing makes the model a variable in a pipeline
whose output you review as if it were deterministic: two rounds of the same agent run can
be served by different models, and a review that looked thorough yesterday looks hurried
today because the router picked cheaper. For production reviews, pin a concrete ID and
use a router for experiments, for triage, or where the traffic mix is genuinely unknown.
OpenRouter’s response tells you which model actually served the call, and the bot records
the integration and the token counts, so a surprising diff is traceable rather than
mysterious.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/openrouter-with-ai-git-bot/openrouter-auto-model.png&quot; alt=&quot;Model routing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;582&quot; height=&quot;347&quot;&gt;&lt;figcaption&gt;The model field of an OpenRouter integration with the automatic router entered as the model ID.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;region-choice&quot; tabindex=&quot;-1&quot;&gt;Region choice &lt;a class=&quot;header-anchor&quot; href=&quot;#region-choice&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Three options, each with a fixed API root:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Region&lt;/th&gt;
&lt;th&gt;API root&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Global&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://openrouter.ai/api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No regional restriction; any eligible endpoint may serve the request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EU&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://eu.openrouter.ai/api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prompt and completion are processed in the EU/EEA, the UK or Switzerland.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;US&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://us.openrouter.ai/api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prompt and completion are processed in the US.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In-region routing is a paid OpenRouter account tier, not a free toggle, and it fails
closed: if no endpoint in that region can serve the model, the request errors instead of
quietly leaving the region. That is the behaviour you want in a review pipeline, and it is
also the reason a model that works on &lt;code&gt;Global&lt;/code&gt; can be unavailable under &lt;code&gt;EU&lt;/code&gt; — the
endpoint has to be onboarded for the region.&lt;/p&gt;
&lt;p&gt;The bot does not take your word for the entitlement. On save it reads the key’s
&lt;code&gt;allowed_data_regions&lt;/code&gt; and rejects a region the key does not list; an omitted list is
accepted only for &lt;code&gt;Global&lt;/code&gt;. Changing the region later re-checks the retained key, so a
plan downgrade surfaces on the next edit rather than on the next review.&lt;/p&gt;
&lt;div class=&quot;mermaid&quot;&gt;flowchart LR
  A[Request] --&amp;gt; B[Region host]
  B --&amp;gt; C[Key check]
  C --&amp;gt; D[Data policy]
  D --&amp;gt; E[Parameters]
  E --&amp;gt; F[Endpoint]
&lt;/div&gt;
&lt;h2 id=&quot;zdr-and-data-collection&quot; tabindex=&quot;-1&quot;&gt;ZDR and data collection &lt;a class=&quot;header-anchor&quot; href=&quot;#zdr-and-data-collection&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Two settings, two independent filters, both on the integration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Provider data collection&lt;/strong&gt; — &lt;code&gt;Deny&lt;/code&gt; (default) or &lt;code&gt;Allow&lt;/code&gt;. Sent as
&lt;code&gt;data_collection&lt;/code&gt; in the routing policy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Require zero data retention (ZDR)&lt;/strong&gt; — off by default. When on, only endpoints with a
zero-retention policy are eligible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ordering matters and the bot does not soften it: ZDR wins over &lt;code&gt;Allow&lt;/code&gt;. With ZDR
enabled and data collection set to &lt;code&gt;Allow&lt;/code&gt;, retention-free endpoints are still the only
ones considered — &lt;code&gt;Allow&lt;/code&gt; does not override ZDR, it only stops being the constraint that
binds. Both values are stored as selected rather than normalised into something
contradictory, and if no endpoint satisfies the combination the request fails explicitly
instead of falling back to a weaker policy.&lt;/p&gt;
&lt;p&gt;Two details that make this hold up rather than just look good:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No plugins.&lt;/strong&gt; The bot disables OpenRouter’s plugins on every request — web, file
parser, response healing, context compression and the Pareto router. Those run outside
the inference path and carry their own retention, and context compression in particular
rewrites the prompt in ways a tool-calling agent did not plan for. Account-level
&lt;strong&gt;Prevent overrides&lt;/strong&gt; settings can force plugins back on; keep the OpenRouter account
free of forced plugins if the policy is the point.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No retained payloads by default.&lt;/strong&gt; The optional raw-payload audit
(&lt;code&gt;AI_USAGE_RAW_PAYLOADS_ENABLED&lt;/code&gt;) is off, so enabling ZDR does not leave a copy of the
prompt in your own database.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One honest limitation belongs here: OpenRouter’s own retention documentation describes a
content-screening exception that applies to ZDR traffic as well. If your requirement is a
signed data-processing agreement rather than a routing flag, read their
&lt;a href=&quot;https://openrouter.ai/docs/guides/features/zdr&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ZDR page&lt;/a&gt; and their terms before you
treat the checkbox as the whole answer.&lt;/p&gt;
&lt;h2 id=&quot;what-the-bot-pins-on-every-request&quot; tabindex=&quot;-1&quot;&gt;What the bot pins on every request &lt;a class=&quot;header-anchor&quot; href=&quot;#what-the-bot-pins-on-every-request&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The routing policy is not the only thing that is fixed. Each OpenRouter call from
AI-Git-Bot sends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;require_parameters: true&lt;/code&gt; — the endpoint must support the parameters the bot sends,
which for an agent run means tool calling and the token limits. An endpoint that would
silently ignore tools is not eligible.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;allow_fallbacks: false&lt;/code&gt; — no provider fallback. A request that no eligible endpoint
can serve fails. For a review this is the right trade: a fallback to a provider with a
different retention policy or a weaker parameter set is worse than a red build.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_tokens&lt;/code&gt;, not &lt;code&gt;max_completion_tokens&lt;/code&gt; — OpenRouter’s token-cap dialect. The generic
OpenAI integration keeps using the OpenAI field name.&lt;/li&gt;
&lt;li&gt;The plugin opt-outs above.&lt;/li&gt;
&lt;li&gt;App attribution headers, so the traffic shows up under the AI Git Bot entry in
OpenRouter’s app directory and rankings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reasoning details from models that emit them are preserved across tool continuations in
memory, separately from the visible answer and the session history — the same mechanism
that keeps a native tool-calling loop consistent on the other providers.&lt;/p&gt;
&lt;h2 id=&quot;watching-the-spend&quot; tabindex=&quot;-1&quot;&gt;Watching the spend &lt;a class=&quot;header-anchor&quot; href=&quot;#watching-the-spend&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;AI usage&lt;/strong&gt; page logs every interaction with input, output, cache-write and
cache-read tokens per integration. The cache columns are the ones to look at first with
OpenRouter: an agentic review re-sends the same prefix every round, provider prompt
caching passes through, and a run whose cache-read count stays at zero is paying full
input price on every round. That is usually a model without caching on the serving
endpoint, not a bot misconfiguration.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/openrouter-with-ai-git-bot/openrouter-usage-log.png&quot; alt=&quot;Usage log&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1466&quot; height=&quot;587&quot;&gt;&lt;figcaption&gt;The AI usage page filtered to an OpenRouter integration, with input, output and cache-read token counts.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Reconcile against OpenRouter’s activity view when the numbers look off: the bot counts
what the provider reported, and OpenRouter is the side that knows the price of the model
that actually served the call.&lt;/p&gt;
&lt;h2 id=&quot;errors-and-what-they-mean&quot; tabindex=&quot;-1&quot;&gt;Errors and what they mean &lt;a class=&quot;header-anchor&quot; href=&quot;#errors-and-what-they-mean&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;HTTP 401 on save&lt;/strong&gt; — the key was rejected. The response body is not surfaced or
logged; provider error bodies can contain account details.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP 402 / 429 during inference&lt;/strong&gt; — credits exhausted or rate limited. Check the
OpenRouter account, not the bot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP 404 during inference&lt;/strong&gt; — the model is unavailable, or no route satisfies the
region and ZDR policy. With &lt;code&gt;EU&lt;/code&gt; selected this is the common shape of “works on Global”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;“Provider overloaded”&lt;/strong&gt; — 503/529 from the upstream endpoint. The retry decorator
backs off and retries, and posts a comment on the pull request or issue saying when the
next attempt happens. Authentication, prompt-too-long and malformed responses are not
retried; they are handled or reported.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;when-not-to-use-it&quot; tabindex=&quot;-1&quot;&gt;When not to use it &lt;a class=&quot;header-anchor&quot; href=&quot;#when-not-to-use-it&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If the requirement is a provider contract with the model vendor directly — a specific
data-processing agreement, a dedicated deployment, a fixed price — the router sits in the
way, and the bot’s Anthropic or OpenAI integration is the shorter path. OpenRouter earns
its place where you want several model families, one bill, and a policy you can set per
request. Within the bot, that is the difference between “this integration reviews with
this model” and “this integration reviews with this model, in this region, without
retention”.&lt;/p&gt;
&lt;p&gt;Feedback is welcome — use the
&lt;a href=&quot;/#services&quot;&gt;contact form&lt;/a&gt;, send an email, or open an
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/issues&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;issue on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Tom Seidel</name>
    </author>
<category term="openrouter"/>
<category term="setup"/>
<category term="privacy"/>
  </entry>
  <entry>
    <title>From issue to pull request: running the coding agent</title>
    <link href="https://gitbot.eu/articles/ai-git-bot-coding-agent/" rel="alternate" type="text/html"/>
    <id>https://gitbot.eu/articles/ai-git-bot-coding-agent/</id>
    <published>2026-11-06T00:00:00.000Z</published>
    <updated>2026-11-06T00:00:00.000Z</updated>
<summary>The implementation agent turns a triaged issue into a pull request on its own. What the setup has to get right, how to keep a weaker model on the rails, and where it still struggles on big repositories and long issues.</summary>
    <content type="html">&lt;p&gt;The coding agent — the &lt;em&gt;implementation agent&lt;/em&gt; in the workflow list — is the part
of AI-Git-Bot that ends with a pull request instead of a comment. Assign a bot to
an issue and it clones the repository, works out which files are involved, edits
them, runs your build, and opens the PR for review. It never merges — the last
step stays human.&lt;/p&gt;
&lt;p&gt;What follows is the practical side of that workflow: the four objects that have
to exist before the first run, the settings that decide whether a small model
produces something usable, how to plug in your own validation command, and what
to do when the repository or the issue is bigger than one run. The reference
documentation lives in the repository:
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/blob/main/doc/CODING_AGENT.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Coding Agent&lt;/a&gt;,
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/blob/main/doc/AGENT.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Issue Agents&lt;/a&gt;,
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/blob/main/doc/TOOL_CALLING.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Tool Calling&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;two-kinds-of-rounds&quot; tabindex=&quot;-1&quot;&gt;Two kinds of rounds &lt;a class=&quot;header-anchor&quot; href=&quot;#two-kinds-of-rounds&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;mermaid&quot;&gt;flowchart LR
  A[Issue assigned] --&amp;gt; B[Clone]
  B --&amp;gt; C[Explore]
  C --&amp;gt; D[Edit]
  D --&amp;gt; E[Validate]
  E --&amp;gt;|fails| D
  E --&amp;gt;|passes| F[Pull request]
&lt;/div&gt;
&lt;p&gt;A run is a loop, and the loop has two flavours of round. Read-only rounds
(&lt;code&gt;rg&lt;/code&gt;, &lt;code&gt;tree&lt;/code&gt;, &lt;code&gt;ctags-signatures&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;) fetch context without spending an edit
attempt. Rounds that write or validate do spend one. The two budgets are
separate, and reads stop being free once the read budget is used up: further
reads are charged to the write budget instead. That is why a run can stop for
lack of rounds having never reached the change — it read too much.&lt;/p&gt;
&lt;h2 id=&quot;setting-it-up&quot; tabindex=&quot;-1&quot;&gt;Setting it up &lt;a class=&quot;header-anchor&quot; href=&quot;#setting-it-up&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Four objects in the admin UI, in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AI Integration&lt;/strong&gt; — provider, model, key, and &lt;strong&gt;Enable native tool calling&lt;/strong&gt;
(on for frontier models). For Anthropic, leave prompt caching on; an agentic
loop re-sends the whole prefix every round and cache reads are roughly a
tenth of the input price.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git Integration&lt;/strong&gt; — a token with repository write access (branches, pushes,
pull requests) and issue write access (progress comments).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System prompts&lt;/strong&gt; (under &lt;em&gt;System settings&lt;/em&gt;) — the prompt sets a bot can use.
Clone the default set for your bot instead of editing the default, and edit
its &lt;strong&gt;Issue-Agent System-Prompt&lt;/strong&gt;; that is what the coding agent runs with.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bot&lt;/strong&gt; — bot type &lt;strong&gt;Coding bot&lt;/strong&gt;, &lt;em&gt;Issue-Assigned Workflow Configuration:
Issue: Coding Agent&lt;/em&gt;, plus the prompt set and a &lt;strong&gt;Tool Configuration&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-coding-agent/bot-issue-workflow.png&quot; alt=&quot;Bot configuration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1649&quot; height=&quot;836&quot;&gt;&lt;figcaption&gt;The bot form: coding bot type, issue-assigned workflow, prompt set and tool configuration.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Then point the repository webhook at the URL shown on the bot page and enable
the &lt;strong&gt;Issues&lt;/strong&gt; event, and make sure whoever triggers the bot can be trusted with
your AI budget — the bot form’s user whitelist is the cheapest guard there is.&lt;/p&gt;
&lt;p&gt;The one setting people get wrong is the &lt;strong&gt;Tool Configuration&lt;/strong&gt;. It is not a
permission list in the narrow sense: it is the entire tool surface the model
sees, and it is re-sent on every round. Leave out &lt;code&gt;dotnet&lt;/code&gt; or &lt;code&gt;mvn&lt;/code&gt; and the
agent is told in its own prompt that validation is mandatory, cannot comply, and
loops until the retry budget is gone. Tick the toolchains the image actually
contains, and nothing else.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-coding-agent/tool-configuration.png&quot; alt=&quot;Tool configuration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1329&quot; height=&quot;892&quot;&gt;&lt;figcaption&gt;A tool configuration with the file tools, the read-only context tools and one validator selected.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Branches follow &lt;code&gt;{prefix}issue-{number}&lt;/code&gt; — &lt;code&gt;ai-agent/issue-42&lt;/code&gt; with the default
prefix. &lt;code&gt;AGENT_ALLOWED_REPOS&lt;/code&gt; limits the whole feature to a list of repositories,
which is worth setting before you let anyone assign the bot.&lt;/p&gt;
&lt;h2 id=&quot;what-a-run-looks-like-on-the-issue&quot; tabindex=&quot;-1&quot;&gt;What a run looks like on the issue &lt;a class=&quot;header-anchor&quot; href=&quot;#what-a-run-looks-like-on-the-issue&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The bot confirms that it picked the issue up, then posts a short plan for each
round, the validation output when something fails, and finally the pull request.
For a run on a repository you have not tried yet, watch the timeline rather than
the result: the rounds tell you whether the model understood the codebase or is
guessing at paths.&lt;/p&gt;
&lt;p&gt;One reading tip: the plan comment is posted &lt;em&gt;before&lt;/em&gt; the tool call runs. It says
what the model is about to do, not what happened next. The evidence is the
comment that follows — or the diff.&lt;/p&gt;
&lt;p&gt;If a session gets stuck, comment &lt;code&gt;try again&lt;/code&gt;, &lt;code&gt;please retry&lt;/code&gt; or &lt;code&gt;redo&lt;/code&gt; on the
issue. The agent sees the previous conversation and usually corrects itself.&lt;/p&gt;
&lt;h2 id=&quot;when-the-model-is-small&quot; tabindex=&quot;-1&quot;&gt;When the model is small &lt;a class=&quot;header-anchor&quot; href=&quot;#when-the-model-is-small&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Frontier models call tools reliably; small and local ones often do not. The
first lever is the transport, not the prompt: turn &lt;strong&gt;Enable native tool calling&lt;/strong&gt;
off for that integration. The bot then describes the tools in the prompt and
parses a JSON answer instead of using the provider’s tool API. It costs more
tokens, and it is the path that has seen the most model/provider combinations.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-coding-agent/ai-integration-tool-calling.png&quot; alt=&quot;Tool calling switch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1201&quot; height=&quot;311&quot;&gt;&lt;figcaption&gt;The tool-calling section of an AI integration, with native tool calling switched off for a local model.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;What does not help is tightening the budgets. The coding agent is not told how
many rounds it has left, so it cannot plan around a cap — lowering
&lt;code&gt;AGENT_BUDGET_MAX_ROUNDS&lt;/code&gt; or &lt;code&gt;AGENT_BUDGET_MAX_CONTENT_ROUNDS&lt;/code&gt; does not make a
small model work more efficiently, it only stops the run sooner, and the issue
ends up with a failure comment instead of a branch. &lt;code&gt;AGENT_BUDGET_MAX_TOKENS_PER_CALL&lt;/code&gt;
is the output budget of a single call: halve it and a long patch plan is cut in
half, which is a failed run, not a cheaper one. Leave all three at their defaults;
if runs keep ending for lack of rounds, raise them.&lt;/p&gt;
&lt;p&gt;What helps is giving the model less to hold at once:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fewer tools.&lt;/strong&gt; Every tool descriptor is re-sent on every round, and every one
of them is a choice the model can get wrong. The tool configuration from the
setup is the cheapest lever there is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A smaller tree on the first run.&lt;/strong&gt; &lt;code&gt;AGENT_CONTEXT_MAX_TREE_FILES&lt;/code&gt; puts up to
500 paths into the opening prompt; 120 is plenty and leaves less to sift.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A starting point.&lt;/strong&gt; One or two file paths in the issue body are worth several
exploration rounds, and they cost a sentence.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A smaller change.&lt;/strong&gt; One issue, one change, a handful of files. A small model
asked for a refactor will produce something plausible and wrong, and the review
will cost more than writing it yourself.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two settings belong to this list as well. Set the integration’s &lt;strong&gt;context window&lt;/strong&gt;
to the model’s real window; it is what decides when the runtime starts dropping
history mid-run, and a wrong value either fires too late or too early.&lt;/p&gt;
&lt;p&gt;For thinking-style local models served through an OpenAI-compatible API,
&lt;code&gt;OPENAI_CHAT_TEMPLATE_KWARGS&lt;/code&gt; (for example &lt;code&gt;{&amp;quot;enable_thinking&amp;quot;: false}&lt;/code&gt;) is often
the difference between a tool call and a paragraph of reasoning about one.&lt;/p&gt;
&lt;p&gt;Finally, the prompt. The coding agent runs on the &lt;strong&gt;Issue-Agent System-Prompt&lt;/strong&gt;
of the prompt set selected in the bot form (&lt;em&gt;System settings → System prompts&lt;/em&gt;).
A small model follows the rule it read last far better than the tenth one, so
shorten it there: name the validator it should run, say that a change is not
done until it has been verified, and drop the rest.&lt;/p&gt;
&lt;h2 id=&quot;custom-validation-with-execute&quot; tabindex=&quot;-1&quot;&gt;Custom validation with &lt;code&gt;execute&lt;/code&gt; &lt;a class=&quot;header-anchor&quot; href=&quot;#custom-validation-with-execute&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Validation is what turns “the agent says it changed something” into “the change
compiles”, and it needs a command. Repositories with a conventional build have
one. Documentation sites, infrastructure repositories and anything driven by a
script do not — for those there is the &lt;strong&gt;&lt;code&gt;execute&lt;/code&gt;&lt;/strong&gt; tool.&lt;/p&gt;
&lt;p&gt;Enable it in the bot’s tool configuration like any other validator, commit the
script with its executable bit, and the agent calls it by repository-relative
path:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;execute scripts/validate.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/usr/bin/env bash
set -euo pipefail

dotnet build projects/hub/Hub.sln -c Release --nologo
dotnet test projects/hub/tests/web-ui/Hub.WebUi.Tests.csproj &#92;
  --no-build --nologo
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git update-index --chmod=+x scripts/validate.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The contract is deliberately narrow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exit code &lt;code&gt;0&lt;/code&gt; means validation passed. Anything else fails the round, and the
captured stdout/stderr goes back to the model &lt;em&gt;and&lt;/em&gt; onto the issue — exactly
like a failing &lt;code&gt;mvn test&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The script runs directly, never through a shell, with the workspace as its
working directory. Arguments after the path are passed through verbatim.&lt;/li&gt;
&lt;li&gt;It must match the committed version. &lt;code&gt;execute&lt;/code&gt; refuses a script the run has
modified, staged or added, so the agent cannot make validation pass by editing
the validator.&lt;/li&gt;
&lt;li&gt;It is bounded by &lt;code&gt;AGENT_VALIDATION_TOOL_TIMEOUT_SECONDS&lt;/code&gt; (300 by default).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point shapes the script: keep it under the timeout, make it print the
failing command’s output rather than a summary, and avoid network calls. A
validator that takes four minutes on a good day will time out on a bad one, and
a timeout looks to the model like a broken change.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-coding-agent/tool-configuration-execute.png&quot; alt=&quot;execute in the tool configuration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1406&quot; height=&quot;413&quot;&gt;&lt;figcaption&gt;The execute validator enabled in a tool configuration, next to the language toolchains.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;execute&lt;/code&gt; is additive — it never replaces &lt;code&gt;mvn&lt;/code&gt; or &lt;code&gt;npm&lt;/code&gt;. Repositories with a
real build command should keep using it, and use &lt;code&gt;execute&lt;/code&gt; only for the extra
checks the build does not cover.&lt;/p&gt;
&lt;h2 id=&quot;pitfalls-worth-knowing&quot; tabindex=&quot;-1&quot;&gt;Pitfalls worth knowing &lt;a class=&quot;header-anchor&quot; href=&quot;#pitfalls-worth-knowing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Validation off means a green comment and no build.&lt;/strong&gt; With
&lt;code&gt;AGENT_VALIDATION_ENABLED=false&lt;/code&gt; the run finishes as soon as the workspace has
a diff, and the success comment says nothing about whether the code compiles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool output is capped.&lt;/strong&gt; A single tool result is truncated at 10,000
characters. &lt;code&gt;cat&lt;/code&gt; with line ranges is how the agent reads a large file, which
also means it can patch a line range it has only partly seen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A search that finds nothing is a failed tool.&lt;/strong&gt; &lt;code&gt;rg&lt;/code&gt; exits non-zero when
there is no match, and in a round that also writes, that counts against the
attempt budget. It is not a bug you can configure away; expect the occasional
“asking the model to correct” after a legitimate empty search.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Follow-ups remember the conversation, not the issue.&lt;/strong&gt; A follow-up prompt
carries the new comment and the discussion, not the issue description, and the
session history is bounded. After a long thread the agent may genuinely no
longer know what the original issue asked for. Start a new issue for a new
topic instead of reusing the PR.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The comment thread is filled oldest-first.&lt;/strong&gt; The per-comment and total
budgets stop at the character limit, and the oldest comments get there first.
Put the specification in the issue body; the last comment is the worst place
for it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hitting a budget looks like a failed implementation.&lt;/strong&gt; A run that runs out of
rounds reports “I was unable to produce a valid implementation” on the first
run, or “validation failed and I couldn’t fix the issues” on a follow-up —
neither is necessarily true; it may simply have stopped. Read the last rounds
of the timeline before you go looking at the build.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One branch per issue.&lt;/strong&gt; Follow-ups push to the same branch as the PR. Two
features in one issue means two features in one diff.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Polyglot repositories need the validator named.&lt;/strong&gt; The model picks the build
command; in a repository with a JVM service and an npm frontend it will
sometimes pick the wrong one. Say which one counts in the prompt.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The agent can edit dependency files&lt;/strong&gt; but cannot install from a registry you
have not made reachable. A change that needs a new package is a change your
image has to support.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;big-repository-big-issue&quot; tabindex=&quot;-1&quot;&gt;Big repository, big issue &lt;a class=&quot;header-anchor&quot; href=&quot;#big-repository-big-issue&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A repository is large when the clone is slow and the tree is unhelpful; an issue
is large when it describes more than one change. Both are manageable, but not
with the same knobs.&lt;/p&gt;
&lt;p&gt;For the repository:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Raise &lt;code&gt;GITEABOT_WORKSPACES_CLONE_TIMEOUT_SECONDS&lt;/code&gt; (300 by default) — the clone
is shallow, but a monorepo tip still takes time — and put
&lt;code&gt;GITEABOT_WORKSPACES_DIR&lt;/code&gt; on fast local disk rather than on a network mount.&lt;/li&gt;
&lt;li&gt;Keep the exploration tools that do not read whole files: &lt;code&gt;rg&lt;/code&gt;, &lt;code&gt;tree&lt;/code&gt;,
&lt;code&gt;ctags-signatures&lt;/code&gt;, &lt;code&gt;ctags-deps&lt;/code&gt;, &lt;code&gt;git-log&lt;/code&gt;, &lt;code&gt;git-blame&lt;/code&gt;. They are what makes a
large tree navigable in ten rounds.&lt;/li&gt;
&lt;li&gt;Let &lt;code&gt;execute-code&lt;/code&gt; do the filtering. A small Python program can call the same
tools and print only the matches that matter, so a fifty-file sweep costs one
tool result instead of fifty.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENT_MAX_FILES&lt;/code&gt; (20 by default) is a blast-radius limit, not a target. On a
monorepo, name the package in the issue so the agent does not have to discover
the boundary.&lt;/li&gt;
&lt;li&gt;Keep the tool configuration minimal. Every tool descriptor is paid for on every
round of every run.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the issue: split it. A run that has to hold three acceptance criteria and two
subsystems will satisfy one of them and claim all three. If the issue is vague,
let the &lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/blob/main/doc/WRITER_AGENT.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;writer agent&lt;/a&gt;
turn it into a specification first; if it is simply large, cut it into issues
that can each be reviewed in one sitting. And give the agent a starting point —
one or two file paths in the issue body are worth several exploration rounds.&lt;/p&gt;
&lt;h2 id=&quot;start-small&quot; tabindex=&quot;-1&quot;&gt;Start small &lt;a class=&quot;header-anchor&quot; href=&quot;#start-small&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The honest summary: the coding agent is reliable on focused issues in
repositories with a working build command and a validator in the tool
configuration, and it is a coin flip anywhere else. Set it up on one repository,
assign it a small issue, and read the timeline before you trust the result. The
settings above are the ones that decide whether the second run is better than
the first.&lt;/p&gt;
&lt;p&gt;Feedback is welcome — use the
&lt;a href=&quot;/#services&quot;&gt;contact form&lt;/a&gt;, send an email, or open an
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/issues&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;issue on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Tom Seidel</name>
    </author>
<category term="agent"/>
<category term="setup"/>
<category term="validation"/>
  </entry>
  <entry>
    <title>AI-Git-Bot 1.30.0 released</title>
    <link href="https://gitbot.eu/articles/ai-git-bot-1-30-0-released/" rel="alternate" type="text/html"/>
    <id>https://gitbot.eu/articles/ai-git-bot-1-30-0-released/</id>
    <published>2026-11-05T00:00:00.000Z</published>
    <updated>2026-11-05T00:00:00.000Z</updated>
<summary>Review progress comments now reach Azure repositories, the entire configuration can be bootstrapped from — and exported to — a file, and gitbot.eu/trial hands out throw-away instances for risk-free testing.</summary>
    <content type="html">&lt;p&gt;We released AI-Git-Bot 1.30.0 today. The complete list of changes is in the
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/releases/tag/1.30.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;release notes on GitHub&lt;/a&gt;.
Here are the ones worth a closer look.&lt;/p&gt;
&lt;h2 id=&quot;progress-comments-on-azure&quot; tabindex=&quot;-1&quot;&gt;Progress comments on Azure &lt;a class=&quot;header-anchor&quot; href=&quot;#progress-comments-on-azure&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the progress comment is enabled for agentic reviews, it now also appears in
Azure repositories.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-1-30-0-released/review-progress-setting.png&quot; alt=&quot;Review progress setting&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;833&quot; height=&quot;434&quot;&gt;&lt;figcaption&gt;The setting that enables the review progress comment.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;That matters most for reviews you expect to run long: it tells the user that a
review is still running instead of leaving them guessing, and afterwards it makes
it easy to see how long reviews actually take — which is the starting point for
tuning them, for example by keeping a changeset small.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-1-30-0-released/review-progress-comment.png&quot; alt=&quot;Review progress comment&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1226&quot; height=&quot;789&quot;&gt;&lt;figcaption&gt;The progress comment in a Gitea pull request.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;initializing-all-data-from-a-file-based-configuration&quot; tabindex=&quot;-1&quot;&gt;Initializing all data from a file-based configuration &lt;a class=&quot;header-anchor&quot; href=&quot;#initializing-all-data-from-a-file-based-configuration&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If your job is to provision AI-Git-Bot automatically in its final configuration,
the Docker start routine now accepts a configuration document with the required
settings. Every value that can be set in the admin UI can also be supplied through
that file. Details, a generator and an example &lt;code&gt;docker-compose&lt;/code&gt; are linked in
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/blob/main/doc/DEPLOYMENT.md#configuration-document-optional&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;DEPLOYMENT.md&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-1-30-0-released/compose-config-example.png&quot; alt=&quot;Example docker-compose with configuration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1101&quot; height=&quot;610&quot;&gt;&lt;figcaption&gt;An example docker-compose that ships a configuration document.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The reverse direction works as well: the complete configuration of a running
instance can be exported, to back it up or to use it as the base for further
automated installations.&lt;/p&gt;
&lt;figure class=&quot;article-figure&quot;&gt;&lt;img src=&quot;/articles/ai-git-bot-1-30-0-released/config-export.png&quot; alt=&quot;Configuration download&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1218&quot; height=&quot;340&quot;&gt;&lt;figcaption&gt;Downloading the running configuration from the system settings.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;throw-away-instance-for-testing&quot; tabindex=&quot;-1&quot;&gt;Throw-away instance for testing &lt;a class=&quot;header-anchor&quot; href=&quot;#throw-away-instance-for-testing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/trial&quot;&gt;gitbot.eu/trial&lt;/a&gt; now generates a disposable instance, so you can try
AI-Git-Bot in your own environment without risk. The instance is reset to its
original settings on every restart — anything you configured in the UI is gone
afterwards, which is exactly the point.&lt;/p&gt;
&lt;h2 id=&quot;many-small-improvements&quot; tabindex=&quot;-1&quot;&gt;Many small improvements &lt;a class=&quot;header-anchor&quot; href=&quot;#many-small-improvements&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Beyond the three features above, this release includes small refactorings,
performance optimisations and a number of bug fixes.&lt;/p&gt;
&lt;h2 id=&quot;feedback-welcome&quot; tabindex=&quot;-1&quot;&gt;Feedback welcome &lt;a class=&quot;header-anchor&quot; href=&quot;#feedback-welcome&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We would like to hear from you: use the
&lt;a href=&quot;/#services&quot;&gt;contact form&lt;/a&gt;, send an email, or open an
&lt;a href=&quot;https://github.com/tmseidel/ai-git-bot/issues&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;issue on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Tom Seidel</name>
    </author>
<category term="release"/>
<category term="azure"/>
<category term="deployment"/>
  </entry>
</feed>
