The demo goes well. The AI team walks a room of stakeholders through a contract-review agent: it reads a supplier agreement, flags non-standard indemnity clauses, checks them against the policy library of the regional bank where the team works, and drafts a redline summary for legal. It is Python and LangGraph, built in a few weeks.
Then the platform lead speaks. Every production service at the bank is Java and Spring Boot. The security review process, the deployment pipeline, the on-call runbooks, and the observability stack all assume the JVM. “We can’t run this in its current form,” she says. Someone suggests porting it to Java. The estimate comes back at six months.
If you lead architecture at a .NET or Java shop, you have probably seen this meeting. The question is how the prototype becomes a production service without throwing it away or creating an unsupported island.
Why this keeps happening
The root cause is not that Python is unsuitable for production. It is that the agent ecosystem and the enterprise platform evolved in different places.
Most agent frameworks ship Python first, and the data teams who build agents already live there. Meanwhile, the enterprise platform was built over a decade around a different runtime. Service discovery, certificates, retry conventions, and tracing are often implemented as Spring Boot starters or .NET middleware. They work well, but for one language.
So the Python agent arrives without any of the things the platform team relies on to trust a service. It has no identity in the service mesh, no trace context the Java callers understand, and no agreed retry or timeout behavior. The gap is platform capabilities, not syntax.
There is a second, quieter problem: agents are slow. A contract review might take two minutes and a dozen model calls. Enterprise integration patterns assume request/response calls that finish in milliseconds or seconds. Put a long agent run behind a synchronous HTTP endpoint and you have created a timeout problem before writing a line of business logic.
Why the usual workarounds fall short
Teams typically reach for one of two options. Both have real costs.
Rewrite the agent in C# or Java. This gives the platform team something familiar but throws away the velocity that made the prototype possible. JVM and .NET agent frameworks are improving, yet Python usually moves first. Six months later, the port is behind the prototype the AI team kept iterating on.
Bolt on a Python microservice. This keeps the agent in Python, but it is usually done ad hoc. Common symptoms:
- Java services call the agent over plain HTTP with hardcoded URLs.
- Retries and timeouts are configured differently on each side.
- Traces stop at the service boundary, so an incident in the agent looks like a mysterious latency spike in the Java caller.
- Authentication between services is a shared API key.
- Long agent runs time out at the load balancer or the HTTP client.
Ops runs a service they cannot observe. The security review stalls, and the rewrite proposal comes back.
The general approach: make language a deployment detail
The fix is to stop treating cross-language integration as something each service implements, and push it into a shared runtime layer that every service uses regardless of language. A few principles:
- Address services by logical identity, not location. Callers should invoke “contract-review” by name, with discovery and encryption handled outside the application code.
- Secure every hop the same way. Workload identity and mutual TLS should apply to the Python agent exactly as they apply to Java services, with access policies that say which callers may invoke which operations.
- Propagate one trace. A W3C trace context that starts in the Spring Boot gateway should continue through the agent and back, so one trace view shows the whole request.
- Declare resiliency centrally. Timeouts, retries, and circuit breakers belong in configuration that platform engineers own, not in scattered client code.
- Make long work asynchronous and durable. Callers start an agent run, receive an ID, and get the result as an event. The agent’s progress survives crashes and restarts.
None of this requires the AI team to learn Spring. It requires both sides to agree on a neutral contract.
Implementing it with Dapr
Dapr, the CNCF-graduated Distributed Application Runtime, is one practical way to build that layer. It runs as a sidecar next to each application, on Kubernetes, VMs, or self-hosted, and exposes the same APIs to every language.
Service invocation by app ID. The Spring Boot service calls the Python agent by its app ID through its local sidecar. The sidecars handle discovery and encrypt traffic with mTLS by default. Dapr’s Sentry service acts as a certificate authority, issuing SPIFFE-based workload identities, and you can bring your own root certificates to fit existing PKI. Access-control policies restrict which app IDs may call which operations.
Pub/sub for results. Rather than hold a connection open for two minutes, the Java caller publishes a “review requested” event or makes a short invocation that starts the run. The agent publishes a “review completed” event when it finishes. Dapr pub/sub works with brokers your platform team may already run, such as Kafka or RabbitMQ, uses CloudEvents, and supports dead-letter topics.
Shared tracing and metrics. Dapr propagates W3C trace context across service invocation and pub/sub, and exports OpenTelemetry traces. Every sidecar emits Prometheus metrics. The Python agent shows up in the same dashboards as everything else.
Resiliency as configuration. A kind: Resiliency YAML resource defines timeouts, constant or exponential retries, and circuit breakers, applied to apps and components. The platform team owns the policy, so behavior is consistent whatever the caller’s language.
Making the agent itself durable
Transport is half the story. The other half is what happens when the agent pod restarts halfway through a long review. Dapr Workflow provides workflow-as-code with event-sourced history stored in a state store. After a crash, the workflow replays and resumes, and completed activities are not re-executed.
For agents already written in a Python framework, you do not have to rewrite them as workflows by hand. Diagrid, the company founded by Dapr’s creators, publishes a diagrid Python package with integrations for LangGraph, CrewAI, Google ADK, AWS Strands, the OpenAI Agents SDK, Pydantic AI, and others. For a LangGraph agent like the contract reviewer, the change is a wrapper around the compiled graph:
from diagrid.agent.langgraph import DaprWorkflowGraphRunner
compiled = graph.compile() # your existing LangGraph StateGraph
runner = DaprWorkflowGraphRunner(graph=compiled, max_steps=50, name=”contract_reviewer”)
runner.start()
async for event in runner.run_async(input={“contract_id”: “C-2291″}, thread_id=”contract-C-2291”):
print(event[“type”]) # workflow_started, workflow_status_changed, workflow_completed, workflow_failed, workflow_error
runner.shutdown()
The graph logic stays the same, though you need a Dapr sidecar (or a managed runtime) and a state store configured for workflows. As with any vendor integration, verify the behavior against your own failure scenarios before relying on it: kill the pod mid-run and confirm the agent resumes where you expect.
Letting Java or .NET orchestrate
Dapr Workflow has SDKs for .NET, Java, and Python, so the larger business process can stay in the platform team’s language. A Java workflow for supplier onboarding might run credit checks, call the Python contract-review agent through service invocation inside an activity, then wait for an external event carrying the review result before routing to a human approver. Orchestrator code must be deterministic, so keep all I/O, including the agent call, inside activities.
If a team later decides some agents should live natively on the JVM or CLR, that path exists too. Diagrid offers a .NET library for Microsoft Agent Framework and a Java starter for Spring AI, the latter still in early development. That choice can be made per agent, not as a platform-wide rewrite.
For teams that would rather not run the workflow and identity infrastructure themselves, managed options exist. Catalyst from Diagrid is one example of a durable execution platform for AI agents, with deployment models ranging from hosted to self-hosted and air-gapped. Compare it with running open-source Dapr yourself or the managed integration in Azure Container Apps, against your own requirements.
A rollout roadmap
- Agree on the contract first. Define input, output, and error events as CloudEvents schemas both teams review.
- Give the agent an app ID and identity. Deploy it with a sidecar, and write access-control policies that allow only the intended callers.
- Wire tracing end to end. Confirm a single trace spans the Spring Boot caller, the agent, and the result event before going further.
- Move platform policy into configuration. Put timeouts, retries, and circuit breakers for the agent into a resiliency resource owned by platform engineering.
- Make runs asynchronous. Replace any synchronous long-running endpoint with “start run, receive event.”
- Make runs durable. Wrap the agent in a workflow runner and test crash recovery deliberately.
- Hand ops a runbook. Document dashboards, dead-letter handling, and how to inspect a stuck workflow.
Read more: टचस्क्रीन म्हणजे काय ? Touch Screen Information In Marathi
Before the security review, check:
- ☐ The agent has a workload identity and mTLS on every hop
- ☐ Access policies restrict callers by app ID
- ☐ Traces connect the caller and the agent
- ☐ No caller holds a synchronous connection for a full agent run
- ☐ A killed agent process resumes without repeating completed model calls
- ☐ Failed messages land in a dead-letter topic someone monitors
Conclusion
The six-month rewrite is usually a symptom, not a requirement. What the platform team actually needs is for the Python agent to behave like every other service: identifiable, encrypted, traceable, governed by shared policy, and resilient to failure. A language-neutral runtime provides those properties without forcing the AI team out of Python. Keep the agent in Python, make the integration boring, and spend the six months on the next use case instead.