Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

hier-config-ai

PyPI Python License

Network configuration remediation driven by a language model, built on hier-config and PydanticAI.

What it is for

hier-config resolves most configuration differences deterministically. A few it cannot, and its custom workflows guide shows how those are handled today: inspect the default remediation, decide it is wrong, and build the correct one yourself in Python.

This library lets you describe the requirement instead.

The canonical case

An access list needs a new entry ahead of an existing one, so the existing entry must move from sequence 12 to 20. hier-config produces the right end state:

ip access-list extended TEST
  no 12 permit ip 10.0.0.0 0.0.0.7 any
  10 permit ip 10.0.1.0 0.0.0.255 any
  20 permit ip 10.0.0.0 0.0.0.7 any

Between the removal and the re-add, though, the list matches nothing and an implicit deny drops live traffic. Avoiding that is what the manual workflow exists for — a temporary allow-all, a renumbering loop, a cleanup, written in Python and maintained per access list.

Described as a rule instead:

acl_rule = AIRemediationRule(
    description=(
        "Rewrite the access list so its entries end up with the intended "
        "sequence numbers.\n"
        "An entry cannot be renumbered in place. Delete it by number with "
        "'no <seq>', then add it back at its new number.\n"
        "The list must never deny live traffic while it is being "
        "rewritten. Add '1 permit ip any any' as the first command, and "
        "remove it with 'no 1' as the last."
    ),
    lineage=(MatchRule(startswith="ip access-list"),),
    example=AIRemediationExample(
        running_config="ip access-list extended EXAMPLE\n 15 permit ip any any",
        remediation_config=(
            "ip access-list extended EXAMPLE\n"
            "  1 permit ip any any\n"
            "  no 15\n"
            "  10 permit ip 192.0.2.0 0.0.0.255 any\n"
            "  20 permit ip any any\n"
            "  no 1"
        ),
    ),
)

Which produces:

ip access-list extended TEST
  1 permit ip any any
  no 12
  10 permit ip 10.0.1.0 0.0.0.255 any
  20 permit ip 10.0.0.0 0.0.0.7 any
  no 1

The rule matches ip access-list generally rather than one list by name. examples/ollama_acl.py runs this against a local Ollama model, verified with qwen2.5-coder:7b on a laptop — it does not need a frontier model.

The plan is verified, not trusted

The model's plan is applied to the running configuration and re-checked against the intended one. If it does not converge, the difference goes back to the model and it corrects itself.

rule -> prompt -> model -> plan
                            |
                     apply and re-diff
                            |
                 converged? -- no --> tell the model what is still wrong
                            |
                           yes
                            |
                          HConfig

That loop is the point of the library. A plan that reads well and still leaves the device misconfigured is worse than no plan at all.

The scaffolding above is understood: 1 permit ip any any followed by no 1 is a pair whose net effect is nothing. Forgetting the cleanup is rejected — a permit ip any any left in a live access list is a hole.

What it does not do for you

Convergence proves the end state, not the path. Leave the traffic-safety sentence out of the description and the model returns the same unsafe plan hier-config generates, which validation accepts because the end state matches. Ordering constraints have to be stated. That is prose rather than Python, but it is not inferred.

Only send what needs judgment. Deterministic remediation is correct for most configuration, and it is free, instant, and never wrong.

Install

pip install "hier-config-ai[anthropic]"    # or [openai], [google], [bedrock]

Ollama, Azure OpenAI, and OpenRouter speak the OpenAI-compatible API, so they use the openai extra.

Use

The rule above, with the surrounding scaffolding:

import asyncio

from hier_config import HConfig, Platform
from hier_config.models import MatchRule

from hier_config_ai import (
    AIRemediationExample,
    AIRemediationRule,
    AIWorkflowRemediation,
)

running = HConfig.from_text(Platform.CISCO_IOS, open("running.conf").read())
intended = HConfig.from_text(Platform.CISCO_IOS, open("intended.conf").read())

workflow = AIWorkflowRemediation(running, intended)
workflow.set_model("anthropic:claude-sonnet-4-5")
workflow.add_rule(acl_rule)   # the AIRemediationRule shown above

remediation = asyncio.run(workflow.aai_remediation_config())
print("\n".join(remediation.to_lines()))

Add one rule per section that needs judgment. Rules run concurrently, so a device with several of them costs one round trip rather than several. aai_remediation_config() is the async form.

Reviewing a plan before you apply it

result = await agent.run(prompt, deps=deps)
plan = result.output

plan.plan                        # the commands
plan.reasoning                   # why the model chose them
plan.confidence                  # "high" | "medium" | "low"
plan.commands_requiring_review    # commands that can cut reachability

Commands that would reload or wipe the device are rejected outright and never reach you. Commands that are risky but legitimate are listed in commands_requiring_review rather than blocked.

Choosing a model

Any PydanticAI model name works:

workflow.set_model("anthropic:claude-sonnet-4-5")
workflow.set_model("openai:gpt-4.1")
workflow.set_model("google-gla:gemini-2.0-flash")
workflow.set_model("bedrock:anthropic.claude-sonnet-4-5-20250929-v1:0")

For a self-hosted model, build the model object yourself and pass it to set_agent(build_agent(model)).

Caching and rate limiting

from hier_config_ai import ResponseCache, RateLimiter

workflow.set_model(
    "anthropic:claude-sonnet-4-5",
    cache=ResponseCache(ttl_seconds=3600),
    rate_limiter=RateLimiter(max_requests=60, time_window_seconds=60),
)

Both wrap the model rather than the client, so they cover tool calls and retries as well as the first request. Cached payloads contain device configurations, so the cache directory is created private to your user.

Failover and consensus

For ordered failover across providers, use PydanticAI directly:

from pydantic_ai.models.fallback import FallbackModel

workflow.set_agent(build_agent(FallbackModel("anthropic:claude-sonnet-4-5", "openai:gpt-4.1")))

To ask several models the same question and accept only an answer they agree on, use consensus_plan(). Votes are counted on parsed configuration, so two models that write the same configuration differently still agree.

Evaluating changes

Retrieval, prompt edits, and model changes can make output worse as easily as better. evals/ measures whether plans actually converge:

poetry install --with dev,evals --all-extras
poetry run python evals/run_evals.py --model anthropic:claude-sonnet-4-5

This calls a real provider and costs money, so it is not part of CI.

Development

poetry install --with dev --all-extras
poetry run python scripts/build.py lint-and-test

See CONTRIBUTING.md.

License

Apache 2.0. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hier_config_ai-0.2.1a0.tar.gz (33.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hier_config_ai-0.2.1a0-py3-none-any.whl (36.6 kB view details)

Uploaded Python 3

File details

Details for the file hier_config_ai-0.2.1a0.tar.gz.

File metadata

  • Download URL: hier_config_ai-0.2.1a0.tar.gz
  • Upload date:
  • Size: 33.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.14 Linux/6.17.0-1022-azure

File hashes

Hashes for hier_config_ai-0.2.1a0.tar.gz
Algorithm Hash digest
SHA256 ebdbd584eda55d557debd21ff9a5333260f84ecff999034a270ef125b1e31cf1
MD5 9b2b6b1c8e06e39a92b6a6799fa1c8ca
BLAKE2b-256 f444796208e23d75835b4bd700f001752c209f47904f6151b83d158aa6f227b4

See more details on using hashes here.

File details

Details for the file hier_config_ai-0.2.1a0-py3-none-any.whl.

File metadata

  • Download URL: hier_config_ai-0.2.1a0-py3-none-any.whl
  • Upload date:
  • Size: 36.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.14 Linux/6.17.0-1022-azure

File hashes

Hashes for hier_config_ai-0.2.1a0-py3-none-any.whl
Algorithm Hash digest
SHA256 80fba3acefbd19d8214bbaac8a637957e52d87decf4e070775a97f821fdc5350
MD5 625384a970650cc88c8ab84818facbeb
BLAKE2b-256 e24b5c9a9068ec1f15c963f30fbff7ee4f7898aa6f2ee9b51b5f41c2ec7fe21f

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.1a0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page