Галоўная / Артыкулы / Практычныя прытамулі: agentgateway у свеце развіцьба агентных рашэнняў

Практычныя прытамулі: agentgateway у свеце развіцьба агентных рашэнняў

Практычныя прыказкі: agentgateway у свеце развіцьбы на агентных моделях: контракты, перакантрольваннія та спецыяльныя слоты для коду для команд, якіе використоўваюць гэты патэрн.

3809 слоў

Наступныя прытамлівкі паказваюць практычны шлях у свете разработкі з агентамі, акцэнтаваючыся на кантрактах, пераконтралях і месцах для коду, які можна легка заменіць, а не на мотывацыйных аспектах. Калі працуеце на стадыі аглявання, спачатку запісайце кантракт: неабяжлівыя даны, сігнал успеху і тое, што выканаецца у разы ўзельнага нявыполнення. Такі чарткі дапамагае заліцьваты пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшоў, прычына нявыполнення павінна вказываць на адную адпаведальнасць, а не на заплутаны ланцужок задач.

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI(title="Identity Verification Agent")


class VerifyRequest(BaseModel):
    customer_id: str
    document_type: str
    document_number: str


class VerifyResponse(BaseModel):
    customer_id: str
    status: str
    confidence: float
    notes: str


@app.get("/health")
async def health():
    return {"agent": "identity-verification", "status": "ok"}


@app.post("/invoke", response_model=VerifyResponse)
async def invoke(req: VerifyRequest):
    return VerifyResponse(
        customer_id=req.customer_id,
        status="VERIFIED",
        confidence=0.97,
        notes=f"{req.document_type} {req.document_number} matched on file.",
    )


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=9001)
curl -s http://localhost:9001/health
curl -s -X POST http://localhost:9001/invoke \
  -H "Content-Type: application/json" \
  -d '{"customer_id":"CUST-5567","document_type":"passport","document_number":"X1234567"}'

Першы оркестрайтар: паралельныя вызовы з asyncio.gather

Этап «Першы рэканцыратор, паралельны» працюе наявнасць краща, калі яго спрыяваць як мерыемую паверхню. Запісаце адна «золатая» транскрыпцыя, адзін прыклад неудачы і прыметку па абяроце перад расшырэнням масштаба. Спрыяваць этап як кантракт межа вхіднымі дадзеннямі і паверыжанымі выходнымі рэзультатамі. Даце назвы артыфактам, задаце критэрыя успеху і адмовіцца ад тыхоўскага частковага завершэння. Зберагачы стан графа ў простам і типаванам формате. Вкладзеныя блокі маскуюць, який вузел запісаў канкрэтны поле, і спакойваюць працу пасля перарываў.

async def call_agent(client, name, payload):
    try:
        resp = await client.post(f"{AGENTS[name]}/invoke", json=payload, timeout=10.0)
        resp.raise_for_status()
        return resp.json()
    except httpx.HTTPError as e:
        return {"status": "ERROR", "error": str(e)}

@app.post("/open-account")
async def open_account(app_data: AccountApplication):
    async with httpx.AsyncClient() as client:
        identity, history, background, financial, public_records = await asyncio.gather(
            call_agent(client, "identity", {...}),
            call_agent(client, "customer_history", {...}),
            call_agent(client, "background_check", {...}),
            call_agent(client, "financial_capability", {...}),
            call_agent(client, "public_records", {...}),
            ............
            ............
        )
    # decision synthesized from all five results
async def call_agent(agent_name: str, payload: dict) -> dict:
    """Never raises -- every failure mode becomes status='ERROR' so the
    graph can route uniformly instead of crashing."""
    url = f"{AGENTS[agent_name]}/invoke"
    try:
        async with httpx.AsyncClient(timeout=TIMEOUT_SECONDS) as client:
            resp = await client.post(url, json=payload)
            resp.raise_for_status()
            return resp.json()
    except httpx.TimeoutException:
        return {"status": "ERROR", "error": f"{agent_name} agent timed out after {TIMEOUT_SECONDS}s"}
    except httpx.ConnectError:
        return {"status": "ERROR", "error": f"{agent_name} agent is unreachable"}
    except httpx.HTTPStatusError as e:
        return {"status": "ERROR", "error": f"{agent_name} agent returned {e.response.status_code}"}
    except Exception as e:
        return {"status": "ERROR", "error": f"{agent_name} agent call failed: {e}"}


def route_after_identity(state) -> str:
    result = state.get("identity_result") or {}
    if result.get("status") == "ERROR":
        state.setdefault("reasons", []).append(f"Identity check failed: {result.get('error')}")
        return "decline"
    if result.get("status") != "VERIFIED":
        state.setdefault("reasons", []).append("Identity could not be verified.")
        return "decline"
    return "continue"

# ... one routing function per check, same shape ...

builder = StateGraph(ApplicationState)
builder.add_node("identity_check", identity_check)
builder.add_node("customer_history_check", customer_history_check)
builder.add_node("background_check", background_check)
builder.add_node("financial_capability_check", financial_capability_check)
builder.add_node("public_records_check", public_records_check)
builder.add_node("decline", decline_node)
builder.add_node("approve", approve_node)

builder.add_edge(START, "identity_check")
builder.add_conditional_edges("identity_check", route_after_identity,
    {"continue": "customer_history_check", "decline": "decline"})
# ... same pattern chained through all five checks ...
builder.add_edge("decline", END)
builder.add_edge("approve", END)

graph = builder.compile()

Калькі продуктов, адзін планавальнік LLM

Этап работы адаптаванняя LLM для калькulationа цэн на разныя продукты дае найлепыя результаты, калі яго рассматрываць як меравальную плошчу. Запісайце адна ідеальная транскрыпцыя, адзін прыклад неудачы і прыметку па поверненні да пачатковага стану пры расширэнні масштаба. Запісвайце часы выконання і кост токенав або запытаў разам з функцыйнальнымі рэзултатамі. Відразы костаў з самага пачатку запобегае неспакойным рахункам, калі праця пераходзіць з дэмавайшага режыма ў спакульнаныя сераўы. Задайце бюджет на токены на кожны раунд і на кожную сесію. Інструменты-агенты агрэсывна расширваюць контекст; строгі ліміты не дазволяюць дэмам ператварыцца на неспакойныя рахункі.

# A simple starter for all agents
uv run agents/background_check_agent.py &
uv run agents/card_linking_agent.py &
uv run agents/identity_agent.py &
uv run agents/customer_history_agent.py &
uv run agents/public_records_agent.py &
uv run agents/financial_capability_agent.py &
uv run agents/gift_card_compliance_agent.py &
uv run orchestrator_langgraph_llm.py &

chmod a+x ./start_agent.sh
# Run it
./start_agents.sh
(account-opening-agents) krishnansriram@Krishnans-MacBook-Pro account-opening-agents % INFO:     Started server process [22183]
INFO:     Started server process [22184]
INFO:     Started server process [22185]
INFO:     Started server process [22182]
INFO:     Started server process [22186]
INFO:     Started server process [22187]
INFO:     Started server process [22188]
INFO:     Waiting for application startup.
INFO:     Waiting for application startup.
INFO:     Waiting for application startup.
INFO:     Waiting for application startup.
INFO:     Waiting for application startup.
INFO:     Waiting for application startup.
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Application startup complete.
INFO:     Application startup complete.
INFO:     Application startup complete.
INFO:     Application startup complete.
INFO:     Application startup complete.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:9007 (Press CTRL+C to quit)
INFO:     Uvicorn running on http://0.0.0.0:9001 (Press CTRL+C to quit)
INFO:     Uvicorn running on http://0.0.0.0:9005 (Press CTRL+C to quit)
INFO:     Uvicorn running on http://0.0.0.0:9008 (Press CTRL+C to quit)
INFO:     Uvicorn running on http://0.0.0.0:9003 (Press CTRL+C to quit)
INFO:     Uvicorn running on http://0.0.0.0:9002 (Press CTRL+C to quit)
INFO:     Uvicorn running on http://0.0.0.0:9004 (Press CTRL+C to quit)
INFO:     Started server process [22190]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
curl -s -X POST http://localhost:9000/process-enquiry \
  -H "Content-Type: application/json" \
  -d '{
    "enquiry_text": "I would like to open a new checking account",
    "customer_id": "CUST-9003",
    "full_name": "Jordan Alex Smith",
    "date_of_birth": "1990-04-12",
    "document_type": "passport",
    "document_number": "X1234567",
    "declared_annual_income": 95000,
    "address": "123 Main St, Columbus, OH"
  }' | python3 -m json.tool
Handling connection for 9000
{
    "customer_id": "CUST-9003",
    "product_type": "account_opening",
    "planned_steps": [
        "identity",
        "financial_capability",
        "background_check",
        "public_records"
    ],
    "planner_reasoning": "This is a new deposit account opening request. Identity should be verified first for the new customer, followed by financial capability checks needed for account opening. Background screening and public records checks are also required for opening a new deposit account.",
    "decision": "APPROVED",
    "customer_message": "Your account opening request has been approved.",
    "reasons": [
        "All required checks passed."
    ],
    "step_results": {
        "identity": {
            "customer_id": "CUST-9003",
            "status": "VERIFIED",
            "confidence": 0.97,
            "notes": "passport X1234567 matched on file."
        },
        "financial_capability": {
            "customer_id": "CUST-9003",
            "status": "PASS",
            "income_verified": true,
            "estimated_credit_score": 742,
            "affordability_status": "ADEQUATE"
        },
        "background_check": {
            "customer_id": "CUST-9003",
            "status": "PASS",
            "criminal_record_found": false,
            "sanctions_hit": false,
            "watchlist_hit": false,
            "notes": "No adverse findings for Jordan Alex Smith."
        },
        "public_records": {
            "customer_id": "CUST-9003",
            "status": "PASS",
            "address_verified": true,
            "bankruptcy_history": false,
            "litigation_history": false
        }
    }
}
curl -s -X POST http://localhost:9000/process-enquiry \
  -H "Content-Type: application/json" \
  -d '{
    "enquiry_text": "I would like to link a debit card to my checking account",
    "customer_id": "CUST-9002",
    "full_name": "Priya Nair",
    "date_of_birth": "1994-03-08",
    "document_type": "passport",
    "document_number": "X5566778",
    "declared_annual_income": 65000,
    "address": "12 Maple Rd, Dublin, OH",
    "linked_account_number": "ACC-99887766"
  }' | python3 -m json.tool
Handling connection for 9000
{
    "customer_id": "CUST-9002",
    "product_type": "debit_card",
    "planned_steps": [
        "customer_history",
        "card_linking"
    ],
    "planner_reasoning": "This is a debit card request. First check customer history to confirm the customer relationship and whether identity/KYC is already established, then perform card linking to verify the checking account and link the debit card.",
    "decision": "APPROVED",
    "customer_message": "Your debit card request has been approved.",
    "reasons": [
        "All required checks passed."
    ],
    "step_results": {
        "customer_history": {
            "customer_id": "CUST-9002",
            "status": "PASS",
            "existing_customer": true,
            "relationship_years": 3.5,
            "prior_accounts": 1,
            "kyc_status": "CURRENT"
        },
        "card_linking": {
            "customer_id": "CUST-9002",
            "status": "PASS",
            "account_verified": true,
            "notes": "Account ACC-99887766 verified and eligible for debit card linking."
        }
    }
}
# This all that we need to kill our agents - stop_agent.sh
pkill -f "uv run agents/"
pkill -f "orchestrator_langgraph_llm.py"

chmod a+x ./stop_agent.sh
# Execute stop agent
./stop_agents.sh
INFO:     Shutting down
INFO:     Shutting down
INFO:     Shutting down
INFO:     Shutting down
INFO:     Shutting down
INFO:     Shutting down
INFO:     Shutting down
(account-opening-agents) krishnansriram@Krishnans-MacBook-Pro account-opening-agents % INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [22185]
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Waiting for application shutdown.
INFO:     Finished server process [22186]
INFO:     Application shutdown complete.
INFO:     Finished server process [22190]
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [22182]
INFO:     Waiting for application shutdown.
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Application shutdown complete.
INFO:     Finished server process [22184]
INFO:     Finished server process [22187]
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [22188]
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [22183]

Размешчэнне ў кластары

Этап развяжвання ў кластэре працюе найкраща, калі яго спрыяваць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адзін кейс неяўнасці і прыметкі па адвярненню перш чым расширваць масштаб. Зберагчыце настройкі параду ўнутры коду аплікацыі. Файлы сяродавішча, хранільнікі секрэтных дадзеных і флагі функций должны знаходзіцца ў аднам месцы, куды аператары можаць адбавляць без неабходнасці чытання всей структуры. Стан графа должен быць простым і з адзінаковым типам дадзеных. Вярсткаваныя блокі маскуюць, який вузел запісаў канкрэтны поле, і спакоююць продажчыку пасля перарываў. Этап развяжвання ў кластэре працюе найкраща, калі яго спрыяваць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адзін кейс неяўнасці і прыметкі па адвярненню перш чым расширваць масштаб. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшаў, прычына неяўнасці должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцоўку.

kubectl get namespace banking-agents 2>/dev/null || kubectl create namespace banking-agents

Адны універсальны Dockerfile для кожнага агента

Для адаптавання ўніверсальнага Dockerfile для данага этапу неабходна прадзеяванне параметраў, вызначэнне адпаведальнага за выкананне крока і крэтарыяў завершэння працы перад зменыма коду. Аператары должны магчымаць перывыканне крока з вядомай точкі контролю без неабясненага выкарыстоўвання скрытых дадзэнняў. Спрыяце цему этапу як кантракту межа параметрамі і перакананымі рэзультатамі. Дайце назвы артыфактам, вызначыце крэтарыі успеху і не падпісвайцеся на тыхое частковае завершэння задання. Забяжцеся пры справах, якія караюць грошамі або зменяюць даны праўай працы, аб чалавечам узгаджэнні. Компіляцыйныя налашчэння не ўзроўнаўцуюцца з абсягамі бізнес-працы.

FROM python:3.13-slim

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project

COPY agents ./agents

ARG APP_MODULE
ENV APP_MODULE=${APP_MODULE}

CMD uv run python ${APP_MODULE}

Развяртанне кожнага агента по чырах

Для этапа «Развяроўка кожнага агента» неабходна пазначыць вхідныя даны, адпаведальнага за шаг і критэрыя завершэння пры перадзмене коду. Аператары должны магчыма было перзапускаць шаг з вядомай точкі контролю, не прабуючы спадарожваць схованы стан. Запісвайце час выконання і вартасьць токена або запыту разам з функцыйнальнымі рэзултатамі. Відразы вартасцей з самага пачатку запобегае неспакоўным рахункам, калі процес пераходзіць з дэмовай среды ў спяльнаныя сераўеры. Заставіце людзкую апрацоўку для тых крокаў, якія выкарыстоўваюць грошы або зміняюць даны у працэсе. Працэс складання коду не є гарантіяй полнай адпаведнасці бізнес-трэбаў.

docker build -t identity-agent:v1 \
  --build-arg APP_MODULE=agents/identity_agent.py \
  -f Dockerfile.agent .

kind load docker-image identity-agent:v1 --name agentgateway

kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: identity-agent
  namespace: banking-agents
spec:
  replicas: 1
  selector:
    matchLabels: {app: identity-agent}
  template:
    metadata:
      labels: {app: identity-agent}
    spec:
      containers:
      - name: identity-agent
        image: identity-agent:v1
        imagePullPolicy: IfNotPresent
        ports: [{containerPort: 9001}]
---
apiVersion: v1
kind: Service
metadata:
  name: identity-agent
  namespace: banking-agents
spec:
  selector: {app: identity-agent}
  ports: [{port: 80, targetPort: 9001}]
  type: ClusterIP
EOF

kubectl rollout status deploy/identity-agent -n banking-agents --timeout=60s
kubectl get pods -n banking-agents

NAME                                          READY   STATUS    RESTARTS   AGE
background-check-agent-566d595b77-h69zg       1/1     Running   0          19h
card-linking-agent-786f4899-96s6c             1/1     Running   0          19h
credit-limit-agent-7fb6db7b76-b8zzf           1/1     Running   0          19h
customer-history-agent-b765d95fd-2pzh5        1/1     Running   0          19h
financial-capability-agent-5c879c8879-98sgp   1/1     Running   0          19h
gift-card-compliance-agent-75c55c74d4-qzpx4   1/1     Running   0          19h
identity-agent-668c66fff8-stgxt               1/1     Running   0          19h
public-records-agent-66dfd78c8b-qrcvh         1/1     Running   0          19h

Развяроўка рэжыстры

Для стадіі развяроцькі рэжыстрыя неабходна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння пры зміне коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Канфігурацыю трэба знаходзіць за межамі коду прыкладнення. Файлы сераўнавання, хранільнікі секрэтных дадзеных і флагі функцыйяў должны быць у аднам месца, якое аператары можаць пераглядаць, не чытаючы весь ланцуг задач. Неабходна людская апраўда для тых крокоў, якія выкарыстоўваюць грошы або зміняюць даны у працэсе. Прыўязкі пад час компіляцыі не є гарантыяй полнай адпаведнасці працэсу бізнес-трэбаванням. Для стадіі развяроцькі рэжыстрыя неабходна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння пры зміне коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Валічыце маленькія, тэставальныя елементы пра велікія скрыпты. Калі крок не выйшоў, прычына нехарактернага рэзультата должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцуг задач.

Неабяжнае.

docker build -t agent-registry:v1 --build-arg APP_MODULE=agent_registry_service.py -f Dockerfile .
kind load docker-image agent-registry:v1 --name agentgateway

kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: agent-registry
  namespace: banking-agents
spec:
  replicas: 1
  selector:
    matchLabels: {app: agent-registry}
  template:
    metadata:
      labels: {app: agent-registry}
    spec:
      containers:
      - name: agent-registry
        image: agent-registry:v1
        imagePullPolicy: IfNotPresent
        ports: [{containerPort: 9100}]
---
apiVersion: v1
kind: Service
metadata:
  name: agent-registry
  namespace: banking-agents
spec:
  selector: {app: agent-registry}
  ports: [{port: 80, targetPort: 9100}]
  type: ClusterIP
EOF

kubectl rollout status deploy/agent-registry -n banking-agents --timeout=60s

kubectl port-forward -n banking-agents svc/agent-registry 9100:80 &
curl -s http://localhost:9100/agents | python3 -m json.tool
#Execution results
Handling connection for 9100
{
    "agents": [
        {
            "name": "identity",
            "url": "http://identity-agent.banking-agents.svc.cluster.local:80",
            "description": "Verifies a customer's identity documents (passport, license, etc). Needed any time a NEW customer's identity hasn't already been established.",
            "input_schema": {
                "customer_id": "customer_id",
                "document_type": "document_type",
                "document_number": "document_number"
            }
        },
        {
            "name": "customer_history",
            "url": "http://customer-history-agent.banking-agents.svc.cluster.local:80",
            "description": "Looks up existing relationship, prior accounts, and KYC status for a customer. Useful to check whether identity verification can be skipped for an existing customer.",
            "input_schema": {
                "customer_id": "customer_id"
            }
        },
        {
            "name": "background_check",
            "url": "http://background-check-agent.banking-agents.svc.cluster.local:80",
            "description": "Criminal record, sanctions, and watchlist screening. Required for opening a new deposit account; usually not required for issuing a card to an already-verified customer.",
            "input_schema": {
                "customer_id": "customer_id",
                "full_name": "full_name",
                "date_of_birth": "date_of_birth"
            }
        },
        {
            "name": "financial_capability",
            "url": "http://financial-capability-agent.banking-agents.svc.cluster.local:80",
            "description": "Verifies income and estimates a credit score. Required for account opening and for credit card applications; not required for debit or gift cards.",
            "input_schema": {
                "customer_id": "customer_id",
                "declared_annual_income": "declared_annual_income"
            }
        },
        {
            "name": "public_records",
            "url": "http://public-records-agent.banking-agents.svc.cluster.local:80",
            "description": "Checks address verification, litigation, and bankruptcy history. Required for opening a new deposit account.",
            "input_schema": {
                "customer_id": "customer_id",
                "address": "address"
            }
        },
        {
            "name": "credit_limit",
            "url": "http://credit-limit-agent.banking-agents.svc.cluster.local:80",
            "description": "Determines an approved credit limit based on income and the requested limit. Required ONLY for credit card applications.",
            "input_schema": {
                "customer_id": "customer_id",
                "declared_annual_income": "declared_annual_income",
                "requested_credit_limit": "requested_credit_limit"
            }
        },
        {
            "name": "card_linking",
            "url": "http://card-linking-agent.banking-agents.svc.cluster.local:80",
            "description": "Verifies a bank account to link a debit card to. Required ONLY for debit card applications.",
            "input_schema": {
                "customer_id": "customer_id",
                "linked_account_number": "linked_account_number"
            }
        },
        {
            "name": "gift_card_compliance",
            "url": "http://gift-card-compliance-agent.banking-agents.svc.cluster.local:80",
            "description": "Checks a gift card purchase amount against AML limits. Required ONLY for gift card purchases.",
            "input_schema": {
                "customer_id": "customer_id",
                "purchase_amount": "purchase_amount"
            }
        }
    ]
}

Размешчэнне оркестрабірача

Калі працюеце над стадзіяй размешчэння оркестрабірача, спачатку запісайце умовы кантракту: неабяжныі вхідныя даны, сигнал успеху і тое, што выходзіць у разы ў частковай няудачы. Такі список пераканае ў тым, што пазнейшыя змены коду будуць чыстымі. Спрыймайце гэтую стадзію як кантракт межаў вхідных дадзеных і перакананых выходных. Даўце назвы артыфактам, задайце критэрыя успеху і не прабуйце прыйняць частковае завершэнне без паведамлення. Зробіце перапытку пасля дорогіх крокаў. Продовжэнне работы не должна зноў ставіць плату за той самы вызов LLM, калі аператар прабуе зноў запрацаваць пазнейшы вузел.

kubectl create secret generic azure-openai-secret \
  -n banking-agents \
  --from-literal=AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com" \
  --from-literal=AZURE_OPENAI_DEPLOYMENT="gpt-5-1-chat" \
  --from-literal=AZURE_OPENAI_API_KEY="your-key" \
  --from-literal=AZURE_OPENAI_API_VERSION="2025-04-14"
docker build -t orchestrator:v1 --build-arg APP_MODULE=orchestrator_dynamic.py -f Dockerfile .

kind load docker-image orchestrator:v1 --name agentgateway

kubectl apply -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orchestrator
  namespace: banking-agents
spec:
  replicas: 1
  selector:
    matchLabels: {app: orchestrator}
  template:
    metadata:
      labels: {app: orchestrator}
    spec:
      containers:
      - name: orchestrator
        image: orchestrator:v1
        imagePullPolicy: IfNotPresent
        ports: [{containerPort: 9000}]
        env:
        - name: AGENT_REGISTRY_URL
          value: "http://agent-registry.banking-agents.svc.cluster.local:80"
        envFrom:
        - secretRef:
            name: azure-openai-secret
---
apiVersion: v1
kind: Service
metadata:
  name: orchestrator
  namespace: banking-agents
spec:
  selector: {app: orchestrator}
  ports: [{port: 80, targetPort: 9000}]
  type: ClusterIP
EOF

kubectl rollout status deploy/orchestrator -n banking-agents --timeout=60s

kubectl port-forward -n banking-agents svc/orchestrator 9000:80 &
curl -s -X POST http://localhost:9000/process-enquiry \
  -H "Content-Type: application/json" \
  -d '{
    "enquiry_text": "I would like to purchase a $500 gift card",
    "customer_id": "CUST-7001", "full_name": "Jordan Smith", "date_of_birth": "1990-04-12",
    "document_type": "passport", "document_number": "X1234567",
    "declared_annual_income": 95000, "address": "123 Main St, Columbus, OH",
    "purchase_amount": 500
  }' | python3 -m json.tool
Handling connection for 9000
{
    "customer_id": "CUST-7001",
    "product_type": "gift_card",
    "planned_steps": [
        "gift_card_compliance"
    ],
    "planner_reasoning": "This is a gift card purchase, so the only relevant specialist is gift_card_compliance to check the amount against AML limits. No identity, credit, account, or background screening steps are needed for this request.",
    "decision": "APPROVED",
    "customer_message": "Your gift card request has been approved.",
    "reasons": [
        "All required checks passed."
    ],
    "step_results": {
        "gift_card_compliance": {
            "customer_id": "CUST-7001",
            "status": "PASS",
            "within_aml_limit": true,
            "notes": "Purchase amount 500.0 vs AML threshold 2000.0."
        }
    }
}

Крок 1 — Разрэшыць крос-неймспэйсовую аднасоўку

Калі вы працуеце над першым крокам «Дазволіць стэйджу», спачатку запісайце умовы контракту: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага невыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Запісвайце час выканання і вартасьць токена або запиту праза функцыональныя рэзультаты. Відразлівая вартасьць з самага пачатку запобегае неспакоўным рахункам, калі працэс пераходзіць з дэмаверсіі ў спяльныя сераўры. Зробіце перапаконтраоль пасля дорогіх крокаў. Функцыя вярнення не должна зноў нараховваць плата за той самы вызов LLM, калі аператар прабуе зноў выконаць пазнейшы вузел.

kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-agentgateway-to-orchestrator
  namespace: banking-agents
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: agentgateway-system
  to:
  - group: ""
    kind: Service
    name: orchestrator
EOF

Крок 2 — Направіць безпосередна да Сэрвісу, без AgentgatewayBackend

Калі працуеце з етапамі «Step 2 Route directly», спачатку запісайце умовы працы: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список контроля дапамагае заліцвачыць пазнейшыя змены ў кодзе. Храніце настройкі парадульна ад коду прыемліка. Файлы сераўіса, хранальнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаюць адбавіць аудыт без неабяжлівага чытання всей структуры.

kubectl apply -f- <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: banking-orchestrator-route
  namespace: agentgateway-system
spec:
  parentRefs:
  - name: agentgateway-proxy
  rules:
  - matches:
    - path: {type: PathPrefix, value: /orchestrator}
    backendRefs:
    - name: orchestrator
      namespace: banking-agents
      port: 80
EOF

kubectl get httproute banking-orchestrator-route -n agentgateway-system

Калі працуеце з етапамі «Step 2 Route directly», спачатку запісайце умовы працы: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список контроля дапамагае заліцвачыць пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы працы над вялікімі скрыптамі. Калі які-небудзь етап нявыпання, прычына нявыпання должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаную структуру працы.

curl -s -X POST http://localhost:8080/orchestrator/process-enquiry \
  -H "Content-Type: application/json" \
  -d '{
    "enquiry_text": "I would like to purchase a $500 gift card",
    "customer_id": "CUST-7001", "full_name": "Jordan Smith", "date_of_birth": "1990-04-12",
    "document_type": "passport", "document_number": "X1234567",
    "declared_annual_income": 95000, "address": "123 Main St, Columbus, OH",
    "purchase_amount": 500
  }' | python3 -m json.tool
# Execution Results
Handling connection for 8080
{
    "customer_id": "CUST-7001",
    "product_type": "gift_card",
    "planned_steps": [
        "gift_card_compliance"
    ],
    "planner_reasoning": "This enquiry is for a gift card purchase. The only required specialist agent is gift_card_compliance to check the $500 amount against AML limits; no identity, background, or account-linking checks are needed for a straightforward gift card purchase.",
    "decision": "APPROVED",
    "customer_message": "Your gift card request has been approved.",
    "reasons": [
        "All required checks passed."
    ],
    "step_results": {
        "gift_card_compliance": {
            "customer_id": "CUST-7001",
            "status": "PASS",
            "within_aml_limit": true,
            "notes": "Purchase amount 500.0 vs AML threshold 2000.0."
        }
    }
}

# 2nd Execution
curl -s http://localhost:8080/orchestrator/health
Handling connection for 8080
# Execution results
{"agent":"dynamic-banking-orchestrator","status":"ok","registry_url":"http://agent-registry.banking-agents.svc.cluster.local:80"}

Што прыносіць agentgateway без дадатковых налаштаванняў для «фільтраў агента»

Этап, які прыносіць agentgateway, работае наяўнай краща, якшо яго розглядаць як мерыябельную паверхню. Зафіксавайце адна ідеальная транскрыпцыю, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Разглядзайце этап як кантракт межа вхіднымі даннымі і паверыжанымі выхіднымі даннымі. Дайце назвы артыфактам, задаце критэрыя успеху і не падзеўляйцеся частым, непূরным выкананнем задачы. Зберагаюце стан графа ў простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў які поле, і спакоююць працу пасля перарываў.

Яшчэ адна важлівая стадзія для банку: маскаванне персональных данных на шляху обработкі LLM

Зрозумела, актуальная адміністратыўная стадія працюе належным чынам, калі яе розглядаць як вимерную паверхню. Запісаўце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Запісвайце часы выканання і вартасць токеноў або запытаў па боку ад функцыйнаых рэзультатаў. Візуабельнасць вартасцей з самага пачатку запобегае неспакойным рахункам, калі процес пераходзіць з дэмавайнога режыма ў спяльныя сераўры. Задаце бюджет на токены на кожны раунд і на кожную сесію. Інструменты-агенты агрэсывна расширваюць контекст; строгі ліміты не дазволяюць дэмам ператварыцца на неспакойныя рахункі.

Обмежэнне частоты запытаў

Этап абсалютавання частоты выконання працюе наяўней, калі яго спрыяваць як мерыемую структуру. Зберагучы адна ідеальная версія логаў, адзін прыклад неудачы і запіс пра вярненне да пачатковага стану, перш чым расширваць сферу дзеяння. Хавайце настройкі за межамі коду прыемлівача. Файлы сераўнавальных средоў, хранільнікі секрэтных дадзеных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць адбавляць контроль, не чытаючы весь ланцуг дзеяння. Хавайце стан ланцуга дзеяння простым і з адазначанымі типамі дадзеных. Вкладненыя блокі дадзеных маскуюць інфармацыю пра тое, який вузел запісаў кожны поль і спакоююць продажчэнне дзеяння пасля перарываў. Этап абсалютавання частоты выконання працюе наяўней, калі яго спрыяваць як мерыемую структуру. Зберагучы адна ідеальная версія логаў, адзін прыклад неудачы і запіс пра вярненне да пачатковага стану, перш чым расширваць сферу дзеяння. Валічыце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшаў, прычына неудачы должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцуг дзеяння.

kubectl apply -f- <<EOF
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
  name: banking-orchestrator-ratelimit
  namespace: agentgateway-system
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: banking-orchestrator-route
  traffic:
    rateLimit:
      local:
      - requests: 60
        unit: Minutes
        burst: 10
EOF
kubectl get agentgatewaypolicy banking-orchestrator-ratelimit -n agentgateway-system
NAME                             ACCEPTED   ATTACHED   AGE
banking-orchestrator-ratelimit   True       True       62s
for i in $(seq 1 75); do
  curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/orchestrator/health
done | sort | uniq -c
# Execution results
Handling connection for 8080
Handling connection for 8080
Handling connection for 8080
Handling connection for 8080
............................
............................
Handling connection for 8080
Handling connection for 8080
Handling connection for 8080
Handling connection for 8080
  70 200
   5 429

Чэрніця для аператывных дзеянняў

У стадії практычнага чэк-лісту неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтарыя выходу пры зміне коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан.

Дакументаваць трэба як шлях успеху, так і шлях вярнення да нормальнага стану. Перапрыбуткі, людзкія перакрыцця і обробка некоректных паведамленняў є частью продукту, а не якімсь пазнейшым дапрацоўкам.

Неабяжна прыняць людзкую згоду для тых крокаў, якія выкалічваюць грошы або зменяюць даны ў працэсе виробніцтва. Компіляцыйныя налашчэнні не є гарантыяй полнай адпаведнасці продукту выклікам.

Напісаць кароткі посібнік: як роцыяваць клучы, як спрачыслаць чергу, як анулюваць пярэдніе змены.

Валіць маленькія, тэставаныя елементы працы над велікімі скрыптамі. Калі крок не выйшоў, прычына нехарактэрыстыкі должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач.

Неабяжна людская празначэнне для тых элементаў, якія выдвайуць грошы або зменяюць данні праработкі. Працаванне ў часе компілявання не абяжаецца пачынкамі бізнес-процэсаў.

Перш чым пераводзіць стэк, заморажуйце версіі, зафіксавайце «золаты» транскрыпты для критычных ліній працы і паказвайце крокі для адвярнення змян. У спадзеленых средах неабходны ліміты частоты, перакананні ў правах на викорыстоўванне та чысты власнік для ротацыі секрэтных даных. Валіце надзейнасць працы над крэатывнымі, адзінразовымі дамах.

Запіс для eb02393af8f9: не кладзіце ключы прадаўцаў у репазітарый, задаце верхнюю межу токенаў на сесію і храніце транскрыпты празаўседы ў фіксатырах eval, каб пазнейшыя замены модэляў заставаліся парабяльнымі.