에이전트 서버

에이전트 서버는 에이전트 코드를 서비스로 전환하는 라이브러리입니다. 에이전트 루프를 HTTP 서버로 감싸고, 클라이언트가 에이전트를 실행하기 위해 호출하는 API를 정의하며, 클라이언트 연결을 관리하고, 실행 중단 시 어떤 일이 일어나는지 결정합니다. 에이전트 서버는 에이전트 런타임에서 실행됩니다. 레이어들이 어떻게 맞물리는지 알고 싶다면 Azure Databricks에 에이전트 배포를 참고하세요.

Agent servers on Azure Databricks

Azure Databricks는 세 개의 에이전트 서버를 제공합니다. 신규 에이전트의 경우 Databricks는 DurableAgentServer를 권장합니다.

에이전트 서버 패키지 클라이언트 API 지속 가능한 실행 에 의해 사용됨
DurableAgentServer (권장) databricks_agentkit, databricks-agentbricks 패키지에 있는 /api/invocations의 Invocation API: 동기화, 스트리밍, 백그라운드 실행, 스트림 재연결을 지원하는 실행 프로비저닝을 수행하고 복구 핸들러를 통한 크래시 복구를 제공하는 런타임 스토어 agentbricks deploy Agent Bricks CLI로 생성하는 프로젝트들
LongRunningAgentServer (레거시) databricks_ai_bridge.long_running, 패키지 내 databricks-ai-bridge[agent-server] OpenAI 응답 API는 /responses에서, 백그라운드 실행 및 스트림 재개와 함께 설정한 Lakebase 데이터베이스의 실행 상태 충돌 후에는 새로운 시도가 중단된 시도의 이벤트 로그에서 실행을 계속합니다. agent-openai-advanced 및 agent-langgraph-advanced앱 템플릿
MLflow AgentServer (레거시) mlflow.genai.agent_server, mlflow 패키지에서 OpenAI 응답 API at /responses: 동기식 및 스트리밍 실행 None 기본 앱 템플릿, 예를 들어 agent-openai-agents-sdk

LongRunningAgentServer MLflow AgentServer를 확장하며, 둘 다 MLflow ResponsesAgent 인터페이스를 구현하는 에이전트를 지원합니다. 이 중 하나를 사용하는 에이전트를 배포하고 유지하려면, 레거시 에이전트 서버를 사용하는 Databricks 앱에서 에이전트 실행을 참조하세요. 이 서버들 중 어느 곳에서든 에이전트를 쿼리하려면 Azure Databricks에 배포된 에이전트 쿼리를 참조하세요.

DurableAgentServer

DurableAgentServer Agent Bricks 에이전트 서버입니다. 에이전트 루프를 호출 API를 제공하는 HTTP 서버로 감싸고, 각 실행을 추적하며, 크래시나 재시작으로 중단된 실행을 복구합니다. Agent Bricks CLI로 생성한 에이전트는 기본적으로 DurableAgentServer를 사용합니다.

DurableAgentServer 제공:

  • 모든 요청 모드에 대해 하나의 API: 동기, 스트리밍, 백그라운드 호출, 스트림 재연결까지 모두 동일한 핸들러가 제공합니다.
  • 멱등 호출: 클라이언트가 생성한 호출 ID는 재시도 요청이 중복 실행을 시작하지 않도록 보장합니다.
  • 순서 세션: 같은 세션 내 호출은 한 번에 하나씩, 순서대로 실행됩니다.
  • 지속 실행 상태: 배포 시 실행 상태, 이벤트, 결과는 워커 재시작에도 유지됩니다.
  • 크래시 복구: 서버가 중단된 실행을 감지하고 재시도를 시작합니다.
  • 요청-사용자 권한 부여: 도구는 요청을 보낸 사용자의 권한에 따라 행동할 수 있습니다.
  • Custom endpoints: DurableAgentServer 는 FastAPI 애플리케이션이기 때문에 자신만의 경로를 추가할 수 있습니다.

Requirements

DurableAgentServer 다음과 같은 요건이 있습니다:

  • Python 3.10 이상입니다.
  • databricks-agentbricks 라이브러리를 포함하는 databricks_agentkit 패키지입니다. agentbricks init로 만든 프로젝트는 agentbricks init를 의존성으로 선언합니다.

에이전트를 등록하세요

agentbricks init로 프로젝트를 생성하면 CLI가 대신 이 작업을 해줍니다. 생성된 runtime/main.py는 서버를 생성하고 템플릿의 호출 및 복구 핸들러를 등록하므로, 에이전트 코드 agent/만 편집하면 됩니다. 이 섹션의 단계를 따라 기존 에이전트를 가져오거나 직접 핸들러를 작성하세요.

DurableAgentServer를 생성하고 비동기 호출 핸들러 @app.invoke를 등록합니다. 핸들러는 요청의 input와 호출 컨텍스트를 받아 JSON 직렬화 가능한 결과를 반환합니다. 진행 상황을 이벤트로 context.emit 게시하세요.

from databricks_agentkit import DurableAgentServer, InvocationContext

app = DurableAgentServer()


@app.invoke
async def invoke(input, context: InvocationContext) -> dict:
    await context.emit({"type": "status", "message": "Looking that up"})
    answer = await run_my_agent(input, session_id=context.session_id)
    return {"answer": answer}

하나의 호출 핸들러를 등록할 수 있고, 호출 핸들러가 없으면 서버가 시작되지 않습니다. 핸들러는 모든 요청 모드를 지원합니다: 클라이언트는 결과를 기다리거나, 이벤트를 스트리밍하거나, 백그라운드에서 실행할지 선택합니다.

서버를 로컬에서 실행하려면 agentbricks dev로 시작하세요. agentbricks init로 생성한 프로젝트에는 Uvicorn으로 서버를 실행하는 엔트리포인트와 배포 후 동일한 엔트리포인트를 시작하는 app.yaml 파일이 포함됩니다.

호출 컨텍스트

핸들러의 두 번째 인수는 다음과 같습니다: InvocationContext

Attribute Description
invocation_id 이 호출을 위해 클라이언트가 보낸 ID입니다.
session_id 호출이 속한 세션 또는 클라이언트가 세션을 보내지 않은 경우 None
attempt 시도 횟수. 첫 번째 시도는 1입니다.
is_recovery True 복구 핸들러가 대체 시도를 실행할 때.
emit(event) JSON 이벤트를 저장하고, 스트리밍 클라이언트에게 전달하며, 스트림 내 이벤트의 위치를 반환합니다.
request_auth 에이전트에 요청-사용자 권한 부여가 필요한 경우의 요청-사용자 자격 증명 확인자 그렇지 않으면 None입니다.

호출 API

DurableAgentServer는 /api/invocations에서 호출 API를 제공합니다:

  • POST /api/invocations 호출이 시작된다. 기본적으로 요청은 결과를 기다립니다. 이벤트를 Server-Sent Events로 수신하도록 background 설정하거나, 상태 URL을 즉시 반환하도록 stream 설정하세요.
  • GET /api/invocations/<id> 호출의 상태를 반환하고, 호출이 완료된 후에는 출력을 반환합니다.
  • GET /api/invocations/<id>/events?after=<event-id> 저장된 이벤트를 스트리밍하여 클라이언트가 연결이 끊긴 후 다시 연결할 수 있도록 합니다.

요청 필드, 예제, 응답 형식에 대해서는 Azure Databricks에 배포된 에이전트 쿼리를 참조하세요.

멱등성

클라이언트는 매번 호출할 때마다 UUID id 를 보냅니다. 서버는 호출 기록을 유지하면서 ID를 멱등성 키로 취급합니다: 같은 요청을 다시 보내면 에이전트를 다시 실행하는 대신 기존 호출을 반환합니다. 다른 요청에 ID를 재사용하면 409 오류가 반환됩니다.

Sessions

클라이언트는 session_id를 보내 호출을 하나의 대화로 그룹화할 수 있습니다. 서버는 세션 ID를 input와 별도로 저장하고, 이를 핸들러에 context.session_id로 전달하며, 동일한 세션 ID를 공유하는 호출은 한 번에 하나씩 순서대로 실행합니다. 서버는 호출 ID나 입력만으로 세션을 추론하지 않습니다. 세션 ID가 없으면 호출은 세션리스입니다.

실행 상태

DurableAgentServer 각 호출의 요청, 상태, 하트비트, 이벤트 및 결과를 런타임 스토어에 저장합니다.

  • 로컬 개발: agentbricks dev 프로세스 내 Runtime Store를 사용합니다. 호출 API도 동일하게 동작하지만, 프로세스가 중단되면 실행 상태가 손실되고, 서버는 중단된 작업을 재시작하지 않습니다.
  • 배포된 에이전트: agentbricks deploy는 각 배포의 런타임 스토어를 위해 Azure Databricks가 관리하는 Lakebase 프로젝트에서 전용 데이터베이스를 프로비저닝하고, 재배포 시 이를 재사용합니다. Runtime Store에서 자신의 Lakebase 프로젝트를 사용할 수 없고, 직접 생성하거나 바인딩하지도 않습니다. 결과와 이벤트는 워커 재시작 후에도 유지되며, 에이전트의 모든 인스턴스는 상태 및 재연결 요청을 처리할 수 있습니다. agentbricks deployments delete 배포와 함께 런타임 스토어를 제거합니다.

런타임 스토어는 서버의 실행 상태를 보유합니다. 이는 에이전트가 대화 기록과 장기 기억을 위해 사용하는 세션 및 메모리 저장소와는 별개입니다.

충돌 복구

워커 충돌 또는 재시작으로 중단된 실행을 복구하려면, @app.recover에 복구 핸들러를 등록하세요. 배포된 서버가 런의 하트비트가 멈췄다고 감지하면, 사용 가능한 워커에 대한 교체 시도를 시작하고 원래 입력으로 복구 핸들러를 호출합니다.

@app.recover
async def recover(input, context: InvocationContext) -> dict:
    # Resume from the agent's last checkpoint in the session store,
    # or replay the input if that's safe for your agent.
    return await resume_my_agent(input, session_id=context.session_id)

복구 핸들러를 등록하지 않으면 자동 복구가 꺼지고, 서버가 시작될 때 서버가 경고를 기록합니다.

복구는 다음과 같이 진행됩니다:

  • 회복 시작 시: 실행 중인 각 시도는 몇 초마다 하트비트를 전송합니다. 예를 들어, 워커가 충돌하거나 재시작되거나 재배치 중에 교체되어 하트비트가 멈추면, 서버는 몇 초 내에 오래된 실행을 감지하고 교체 시도를 시작합니다.
  • 복구가 시작되지 않을 때: 핸들러가 예외를 제기하면 호출이 실패하고 서버는 다시 시도하지 않습니다. 복구는 에이전트 코드의 오류가 아니라 중단된 작업자에 적용됩니다.
  • 시도 횟수: 서버가 복구 시도 횟수를 제한하지 않습니다. 교체 시도마다 context.attempt가 1씩 증가합니다. 여러 번 시도한 후 멈추려면, 복구 핸들러에서 context.attempt를 확인하고 오류를 발생시키세요.
  • 수동 복구: 수동으로 복구를 트리거할 수 없습니다. 동일한 호출 ID로 요청을 다시 보내면 새 시도를 시작하는 대신 기존 호출을 반환합니다.

복구는 동일한 호출에 대해 에이전트 코드를 여러 번 실행할 수 있습니다. 중단된 시도는 교체 시도가 시작되기 전에 이미 외부 시스템을 호출했을 수 있으므로, 해당 호출이 멱등성을 갖도록 하세요.

에이전트킷 라이브러리

DurableAgentServer는 databricks_agentkit 패키지에 포함된 AgentKit 라이브러리인 databricks-agentbricks의 일부입니다. agentbricks init에서 가져와 만든 프로젝트입니다. 라이브러리는 다음과 같은 헬퍼를 내보냅니다:

Export Description
DurableAgentServer, InvocationContext 에이전트 서버와 그것이 호출 및 복구 핸들러에게 전달하는 컨텍스트
AgentKitClient 관리형 메모리 및 세션 저장소를 위한 클라이언트입니다. 저장소를 생성하고 가져오며, 저장소의 메모리와 세션을 SessionStore, SessionItem, MemoryStore, Session, MemorySearchResult, 및 Memory 객체로 노출합니다.
configure_tracing, start_trace 에이전트에 MLflow 추적을 설정하고, 작업 단위를 대상으로 trace를 시작하세요.
workspace_client, workspace_headers 에이전트 환경에서 인증된 Databricks SDK WorkspaceClient를 만들거나 직접 HTTP 호출을 위한 인증 헤더를 받으세요.
list_ai_gateway_model_services 에이전트가 Unity 게이트웨이를 통해 호출할 수 있는 모델 서비스를 나열하세요.

라이브러리에는 생성된 템플릿이 각 프레임워크를 세션 스토어와 연결하는 데 사용하는 databricks_agentkit.langgraph 및 databricks_agentkit.openai에 있는 프레임워크 헬퍼도 포함되어 있습니다. 메모리 및 세션 API에 대해서는 Managed agent memory 와 Managed agent sessions를 참조하세요.

사용자 권한 요청

기본적으로 에이전트의 도구는 앱의 서비스 주체의 권한을 가지고 실행됩니다. 요청을 보낸 사용자의 권한으로 도구를 실행하려면 agent.toml에서 사용자 권한을 선언하세요:

  • 관리되는 도구의 경우 도구 항목에 auth = "user"을 설정하세요. MCP 서버, 샌드박스 및 Genie 에이전트용 agentbricks tools add 명령어는 기본적으로 auth = "user"를 작성합니다. 앱 신원을 사용하려면 Pass --auth app를 사용하세요.

  • 코드로 작성한 도구의 경우, 요구사항과 에이전트 브릭스가 추론할 수 없는 API 범위를 선언하세요:

    [auth.user]
    required = true
    additional_api_scopes = ["sql"]
    

에이전트가 사용자 승인을 요구할 때, DurableAgentServer는 신뢰할 수 있는 Databricks Apps 요청 헤더에서 사용자의 자격 증명을 읽어 현재 활성 시도 동안에만 메모리에 저장합니다. 런타임 스토어는 자격 증명을 저장하지 않습니다. 핸들러에서 사용자용 작업 공간 클라이언트를 context.request_auth에서 받으세요:

@app.invoke
async def invoke(input, context: InvocationContext) -> dict:
    user_client = context.request_auth.client_for("user")
    me = user_client.current_user.me()
    return {"answer": f"Hello, {me.user_name}"}

client_for("app") 앱의 서비스 프린시펄을 사용하는 클라이언트를 반환합니다. 시도가 끝나면 리졸버가 닫히므로, 클라이언트를 저장하는 대신 핸들러 내부에서 호출하세요. 에이전트를 로컬에서 agentbricks dev 실행할 때는 client_for("user")는 로컬 자격 증명을 사용합니다.

배포할 때, agentbricks deploy가 도구에 필요한 Databricks Apps 사용자 범위를 요청합니다. 기존 앱에 누락된 스코프를 추가하려면 --allow-user-scope-update를 전달하세요. Databricks 앱에서 권한 부여 구성을 참조하세요.

request-user 호출은 동일한 동기, 스트리밍, 백그라운드 및 재연결 API를 사용합니다. 서버가 사용자의 자격 증명을 저장하지 않기 때문에, 중단된 request-user 호출을 복구할 수 없습니다. 교체 시도는 핸들러가 실행되기 전에 MCP_USER_AUTH_RECOVERY_UNSUPPORTED 오류로 실패합니다.

커스텀 엔드포인트 추가

DurableAgentServer 이는 FastAPI 애플리케이션입니다. 호출 API와 함께 경로를 추가하세요. 다른 FastAPI 앱에 추가하는 것과 같은 방식으로:

@app.get("/status")
async def status() -> dict:
    return {"ready": True}

프레임워크 템플릿

agentbricks init 두 개의 디렉터리를 생성합니다:

  • agent/에는 프레임워크 코드(모델, 프롬프트, 도구)가 포함됩니다.
  • runtime/ 프레임워크를 DurableAgentServer에 연결하는 어댑터와 어댑터의 호출 및 복구 핸들러를 등록하는 진입점을 포함합니다.

어댑터는 각 호출을 프레임워크의 에이전트 루프 호출로 변환하고, 프레임워크의 출력을 이벤트와 결과로 변환합니다. 두 템플릿 모두 복구 핸들러를 등록합니다. LangGraph 템플릿은 세션 스토어의 마지막 체크포인트에서 다시 시작되며, OpenAI 에이전트 SDK 템플릿은 같은 세션에서 요청을 다시 실행합니다. 기존 에이전트를 가져오려면 어댑터와 DurableAgentServer 엔트리포인트를 추가하고, server = "agentbricks"의 [agent] 섹션에서 agent.toml을 설정하세요.

Limitations

  • 기존 배포의 에이전트 서버를 변경할 수 없습니다. DurableAgentServer와 자신의 서버 간에 전환하려면 원하는 agentbricks init --server 옵션으로 새 프로젝트를 만들고 새 이름으로 배포하세요.
  • server에서 agent.toml 필드를 변경해도 기존 서버 코드가 DurableAgentServer로 변환되지 않습니다.
  • 요청-사용자 승인은 server = "agentbricks"이 필요합니다.

추가 리소스