Skip to main content
Connic
Back to BlogTutorial

How to Deploy a Python AI Agent Without Kubernetes

Deploy a Python AI agent without Kubernetes using YAML, plain Python, deployment-gated tests, Git, and a managed EU runtime. Includes working code.

August 12, 202612 min readAuthor: Connic Engineering

To deploy a Python AI agent without Kubernetes, keep the agent definition, Python tools, and release tests in a repository, then run that project on a managed agent runtime. The runtime owns packaging, execution, scaling, deployment, and traces. Your team still owns the agent's behavior and business logic.

The example below is deliberately complete and small. It uses one current EU-hosted connic/* model and one pure-Python tool, so it needs no model-provider account, external API, Dockerfile, Helm chart, or cluster. You can copy the files as written and then replace the sample delivery table with your own service.

What does “without Kubernetes” actually mean?

Your application team delegates the container orchestration layer to a managed runtime. Infrastructure still exists; the platform operator runs it. The team deploys an agent Project instead of managing the underlying containers.

Kubernetes is a capable general-purpose orchestrator. Its official documentation explains how you reference a built container image, then use a Deployment to manage Pods and rollouts. That is useful infrastructure, but it stops below the agent-specific layer: prompts, model calls, tool traces, evaluation, and release assertions are still yours to assemble. Review how Kubernetes describes preparing and referencing container images and managing application rollouts with Deployments.

Production concernKubernetes-based serviceManaged agent runtime
PackagingBuild, scan, tag, and publish an imageBuild the repository into the managed runtime
ExecutionChoose and configure a workload objectRun the named agent from its YAML definition
ScalingConfigure HPA and the required metrics pathSet concurrency controls; runtime scales execution
SecretsConfigure Secrets, encryption, and access policySet environment-scoped variables in the Project
Release qualityAdd agent tests to your CI/CD pipelineRun declarative tests as the deploy gate
DebuggingExport logs and add agent-aware telemetryInspect inputs, outputs, model calls, tools, and cost

Kubernetes horizontal autoscaling depends on resource, custom, or external metrics; queue depth or agent latency normally requires an explicit metrics path. Kubernetes Secrets are stored unencrypted in etcd by default unless you enable protection. Durable log storage and querying also require a cluster-level backend because Kubernetes does not include one. Check the official guidance for configuring Horizontal Pod Autoscaling, hardening Kubernetes Secrets, and adding cluster-level logging. A managed Kubernetes service can remove control-plane work, but these application-layer choices do not disappear.

The complete Python agent project

This project answers delivery questions from a small, deterministic data table. The model must call the tool before it quotes a delivery window, and the test suite verifies that the tool call remains in the execution path.

project structure
delivery-agent/
├── agents/
│   └── delivery-assistant.yaml
├── tools/
│   └── shipping.py
├── tests/
│   └── delivery-assistant.yaml
└── .gitignore

1. Scaffold the repository

The Composer SDK requires Python 3.10 or newer. Install the package and create a project directory:

terminal
python -m pip install connic-composer-sdk
connic init delivery-agent
cd delivery-agent

Create a Connic Project in the dashboard, select an EU deployment region, and authenticate the local directory with connic login. That command writes Project credentials to .connic. Keep the file out of Git:

.gitignore
.connic
.venv/
__pycache__/

2. Define the agent in YAML

The YAML is the operational contract for the agent: model, prompt, callable tools, and guardrails stay visible in code review. This example uses the currentconnic/glm-5.2 model, which needs no separate provider key.

agents/delivery-assistant.yaml
version: "1.0"

name: delivery-assistant
type: llm
model: connic/glm-5.2
description: "Answer delivery-window questions with verified data"

system_prompt: |
  You answer questions about delivery times.
  Always call shipping.estimate_delivery before giving an estimate.
  If the user does not name a country, ask for one without calling the tool.
  Pass an uppercase ISO country code and either standard or express.
  If the tool reports available false, say: "This route is unavailable."
  Never invent a delivery window.

tools:
  - shipping.estimate_delivery

guardrails:
  input:
    - type: prompt_injection
      mode: block
    - type: pii
      mode: redact
  output:
    - type: moderation
      mode: block
    - type: system_prompt_leakage
      mode: block

The four guardrails are a practical production baseline: block prompt injection, redact input PII, moderate output, and block system-prompt leakage. Adjust them to the application rather than treating any default as a complete safety policy. You can review every guardrail mode and execution rule before shipping sensitive workflows.

3. Write the tool as plain Python

A custom tool is an ordinary function under tools/. Type hints define the input schema and the docstring tells the model when the function is useful. Connic discovers the function directly from the file.

tools/shipping.py
DELIVERY_WINDOWS = {
    ("DE", "standard"): (2, 4),
    ("DE", "express"): (1, 2),
    ("FR", "standard"): (3, 5),
    ("FR", "express"): (1, 3),
    ("NL", "standard"): (2, 4),
    ("NL", "express"): (1, 2),
}


def estimate_delivery(country_code: str, service: str = "standard") -> dict:
    """Return the delivery window for a supported country and service."""
    country = country_code.upper()
    normalized_service = service.lower()
    window = DELIVERY_WINDOWS.get((country, normalized_service))

    if window is None:
        return {
            "available": False,
            "country_code": country,
            "service": normalized_service,
        }

    minimum_days, maximum_days = window
    return {
        "available": True,
        "country_code": country,
        "service": normalized_service,
        "minimum_business_days": minimum_days,
        "maximum_business_days": maximum_days,
    }

This implementation has no network dependency, which makes the tutorial reproducible. In a real Project, replace the dictionary lookup with your API or database call and read credentials from environment variables. If the service is private, use Connic Bridge instead of opening an inbound firewall rule. Follow the documentation to implement and expose Python tools or connect the runtime to private services.

4. Add a release-gating test

This agent could return a plausible number after checking the wrong route. The suite asserts that the run completes and that shipping.estimate_delivery appears in the trace with the requested country and service. It also checks the quoted window, the unavailable-route response, and the no-country branch.

tests/delivery-assistant.yaml
version: "1.0"

defaults:
  runs: 1
  timeout_s: 60

tests:
  - name: estimates_standard_delivery_to_germany
    payload: "How many business days does standard delivery to DE take?"
    expected_result: status == "completed" and "2" in output and "4" in output
    expected_tool_calls:
      - shipping.estimate_delivery: params.country_code == "DE" and params.service == "standard" and invocations == 1

  - name: checks_an_unsupported_route
    payload: "Can you ship express to the US?"
    expected_result: status == "completed" and "route is unavailable" in output
    expected_tool_calls:
      - shipping.estimate_delivery: params.country_code == "US" and params.service == "express" and invocations == 1

  - name: asks_for_a_country_before_lookup
    payload: "How long does standard delivery take?"
    expected_result: status == "completed"
    expected_no_tool_calls:
      - shipping.estimate_delivery

Start with one run per case so the deployment gate stays fast. For behavior that is genuinely stochastic, increase runs and set a success threshold below 100. The test reference shows how to configure repeated runs and tool-call assertions.

5. Lint and run in the managed development runner

These commands validate file discovery and start an isolated cloud development runner that uses the same image as production:

terminal
connic lint
connic dev

Inside the interactive dev session, press t to run the synced suites against that active environment and q to exit. Then run connic test for a fresh ad-hoc test run against the configured environment. You can review the managed development loop before connecting Git.

Prove that the gate can fail
Temporarily change the expected tool to shipping.get_quote, then run connic test --filter estimates_standard_delivery_to_germany. The case should fail because the trace contains shipping.estimate_delivery, not the invented tool. Restore the assertion and rerun the suite before you deploy.

6. Deploy through Git

Connect the repository to the Connic Project and map a branch to the target environment. A push to that branch starts the managed Build → Tests → Deploy pipeline. The built image is tested before release, and any failed case stops promotion. Git-connected Projects deploy through this push flow; a Project that is not connected to Git can use connic deploy.

terminal
git add agents tools tests .gitignore
git commit -m "Add delivery assistant"
git push origin main

The same repository can map different branches to development, staging, and production environments, each with isolated configuration and run history. Read how to connect branches and deploy a Project and inspect the deployment test gate.

Evaluate the full code-first platform

See how YAML, Python, Git deployment, EU-hosted models, observability, approvals, and governance fit together beyond this example.

Explore the code-first EU platform

What the managed runtime now owns

Build and execution
Connic builds the repository, runs each agent in the managed runtime, and applies Project limits for run duration and concurrency.
Release gate
The same YAML suite runs in ad-hoc tests and before deployment. A failed case prevents the new image from becoming active.
Agent-aware traces
Every execution records input, output, status, duration, token use, cost, and a hierarchical trace of model calls, tools, middleware, and child agents.
Runtime controls
Guardrails, approvals, environment variables, budgets, connectors, and isolated environments are platform controls rather than separate services.

A container log can tell you that a process wrote an error. An agent trace can show the input, the model step that selected a tool, the exact tool arguments and result, and the final response. That is the useful debugging boundary for agent behavior. See exactly what is captured when you inspect runs and hierarchical traces.

What does this example cost to run?

Separate platform execution from model tokens when you estimate cost. At the published rates checked on August 12, 2026, 1,000 monthly runs averaging 15 seconds produce this platform subtotal:

Line itemCalculationMonthly
Runs1,000 × €0.047€47.00
Compute15,000 seconds × €0.00042€6.30
Platform subtotalBefore model, storage, and Retrieval usage€53.30
How Project credit applies
Developer costs €40/month and includes €40 in monthly Project credit. That credit offsets €40 of total Project-balance usage. Platform execution alone exceeds it by €13.30 in this example; managed-model token charges also debit the balance, so the required purchased credit is €13.30 plus token cost. BYOK inference is billed by the selected provider instead.

The table is arithmetic only. Actual duration and token use depend on the prompt, model, tool calls, and traffic. Check the latest numbers before budgeting. You can review current Project pricing and usage rates and verify current managed-model IDs and token rates.

Where does the data run?

This sample keeps the Connic-operated path in the EU: select an EU Project region, use a connic/* model that runs on EU inference capacity, and execute the pure-Python tool in the managed runtime. That boundary changes when you add an external component. A BYOK provider, custom API, judge, guardrail, or result destination can send data elsewhere if you configure it to do so.

Residency follows the complete request path. The model, tools, storage, traces, and outbound destinations all affect it. Use the detailed boundary to verify which parts of a code-first Project stay in the EU.

When should you still choose Kubernetes?

Use Kubernetes when direct infrastructure control is a product or policy requirement. It remains a strong fit when a platform team already operates a mature cluster, the workload needs custom scheduling or network primitives, policy requires execution inside infrastructure you directly control, or a measured high-volume workload has a better self-hosted total cost.

Choose a managed agent runtime when the differentiating work is the agent: its tools, behavior, integrations, quality, and user experience. The trade is less infrastructure control in exchange for an agent-native release and operations layer. If you already have a framework prototype, you can also see what changes when moving LangChain or ADK code into production.

Methodology and disclosure

Connic publishes this tutorial and is the managed runtime used in the example. Kubernetes claims were checked against the official Kubernetes documentation; Connic syntax, behavior, and pricing were checked against current product code and documentation on August 12, 2026. No performance comparison was run, and Kubernetes can run AI agents. The cost example excludes model tokens, storage, Retrieval, engineering labor, and any external service fees.

Frequently Asked Questions

Yes. With a managed agent runtime, your team can submit agent YAML, plain Python tools, and tests without maintaining a Dockerfile or Kubernetes manifests. Infrastructure still exists, and the platform operator manages it.

Connic is a managed AI agent deployment and orchestration platform with a code-first authoring layer. The Composer SDK defines agents in YAML and tools in Python, while the platform handles builds, deployment, execution, scaling, connectors, tests, traces, evaluation, guardrails, approvals, storage, and governance.

No. It changes who manages the infrastructure. With Kubernetes, your team or cloud platform team owns workload manifests, image delivery, scaling configuration, secrets integration, logging, and agent-aware telemetry. With a managed runtime, the vendor owns that layer and your team owns agent code, configuration, tests, and application behavior.

Yes. Migration still requires review. Reusable plain-Python tool logic can usually stay, while the agent definition moves to YAML. Complex graphs, state, retrieval, callbacks, and framework-specific tracing need manual work. The Connic CLI can generate a migrated project and a report of follow-up items.

Connic-operated platform data can run in a selected EU Project region, and connic/* managed-model inference runs on EU capacity. End-to-end residency depends on every configured component. A BYOK model provider, external tool, judge, custom guardrail, or outbound destination can move data outside the EU.

Kubernetes is a better fit when your organization already has a mature platform team, requires custom scheduling or network primitives, must keep execution inside infrastructure it directly controls, or has validated that a high-volume workload is cheaper to operate itself. A managed runtime fits teams that want to spend engineering effort on agent behavior and product integration instead.

More from the Blog

Tutorial

How to Trigger AI Agents from Kafka Topics

Point a Connic Kafka inbound connector at a topic and every message starts an agent run. Configure the connector, link an agent, deploy, and watch runs.

July 12, 20268 min read
Tutorial

How to Add an AI Agent to Your SaaS Without a Large Engineering Team

A practical, step-by-step path to shipping your first production AI agent with a small team: scope one job, define it in config, connect it to your existing systems, and let a runtime handle the rest.

June 12, 20269 min read
Tutorial

Automated Agent Scoring: AI Agent Evaluation with LLM Judges

Automated agent scoring uses an LLM judge to grade sampled or every matching agent run against criteria you define. Track score trends and alert on regressions.

March 29, 202610 min read
Tutorial

Migrate from LangChain to Production AI Agents

Your LangChain prototype works. Now you need it to handle real traffic. Learn how to migrate existing agent code to a production-grade platform without rewriting from scratch.

March 23, 202611 min read
Tutorial

Database vs. Retrieval: Choosing the Right Storage

Learn when to use Connic's document database for structured CRUD vs. the retrieval for semantic search. Configuration tips and best practices.

March 4, 202612 min read
Tutorial

AI Agents: From Prototype to Production

Your demo works great until you have 1,000 concurrent users. A practical guide to the production requirements most teams find out about too late.

January 10, 202610 min read
Tutorial

Hidden Costs of Self-Hosting AI Agents

We'll just deploy it on Kubernetes. Famous last words. The true cost of self-hosting AI agents versus a managed platform.

December 18, 20257 min read
Tutorial

Add AI Agents to SaaS Without an ML Team

Your customers expect AI features, but you don't have ML engineers. Learn how teams ship AI agents using skills they already have.

December 5, 20258 min read
Tutorial

AI Agent RAG Tutorial: Retrieval With Citations

Build a production RAG agent with scoped retrieval namespaces, read-only permissions, source citations, custom tool wrappers, and regression tests.

November 15, 20259 min read