Skip to content

Usage Recipes

이 문서는 ddd-agent를 실제로 어떤 조합으로 쓰면 되는지 빠르게 결정하기 위한 가이드입니다.

핵심 질문은 보통 아래 3개입니다.

  • LangGraph만으로 시작해도 되는가?
  • human review는 어디에서 켜는가?
  • LangChain은 정확히 어디에 붙이는가?

Recipe 1: LangGraph-Only, Deterministic Agent

가장 가벼운 시작점입니다.

이 조합을 쓰면:

  • workflow orchestration은 LangGraph
  • planning/proposal은 deterministic AgentEngine
  • external dependency는 최소화

이 패턴이 맞는 경우:

  • 먼저 lifecycle과 wiring을 검증하고 싶을 때
  • LLM 없이 domain flow를 먼저 만들고 싶을 때
  • 테스트 친화적인 skeleton이 필요할 때

참고 예제:

  • src/domain_agent/adapters/inbound/cli_demo.py
  • examples/streamlit_review_demo/streamlit_review_demo/app.py
  • examples/autonomous_digest

최소 wiring:

from domain_agent.application.ports import WorkflowDependencies
from domain_agent.application.use_cases import AgentWorkflowService
from domain_agent.adapters.outbound import InMemoryRequestRepository

dependencies = WorkflowDependencies(
    context_provider=DemoContextProvider(),
    agent_engine=DemoAgentEngine(),
    action_executor=DemoActionExecutor(),
    requires_human_review=False,
)

service = AgentWorkflowService(
    request_repository=InMemoryRequestRepository(),
    workflow_dependencies=dependencies,
)

핵심은 LangGraph graph는 그대로 두고, AgentEngine만 deterministic하게 구현해도 end-to-end가 성립한다는 점입니다.

Recipe 2: Review-Enabled LangGraph Flow

사람 검토가 필요한 도메인이라면 이 조합으로 갑니다.

이 조합을 쓰면:

  • workflow 중간에 LangGraph interrupt() 발생
  • ReviewPacket이 review surface로 전달
  • PlanReviewResult로 resume
  • approved action만 실행

이 패턴이 맞는 경우:

  • 운영 변경
  • 대외 API 호출
  • privileged action
  • 사람이 일부 action만 승인해야 하는 경우

참고 예제:

  • examples/operational_change
  • examples/mock_api
  • examples/github_repo_review

핵심 wiring:

result = service.run(
    request.request_id,
    review_handler=my_review_handler,
)

여기서 review_handlerReviewPacket -> PlanReviewResult를 반환하면 됩니다.

즉 review UI가 CLI든 web이든 Slack이든, core workflow는 바뀌지 않습니다.

이 저장소에는 두 개의 review surface가 이미 있습니다.

  • terminal: src/domain_agent/adapters/inbound/cli_review.py
  • browser UI: examples/streamlit_review_demo/streamlit_review_demo/app.py

Recipe 3: LangChain As AgentEngine

LangChain은 AgentEngine 레이어에만 붙이는 것이 가장 자연스럽습니다.

이 조합을 쓰면:

  • domain은 LangChain을 모름
  • workflow는 LangGraph 그대로 유지
  • LangChain은 analysis/plan/proposal preparation만 담당

이 패턴이 맞는 경우:

  • structured output을 받고 싶을 때
  • tool-aware planning을 하고 싶을 때
  • fake engine에서 실제 LLM engine으로 올리고 싶을 때

참고 예제:

  • examples/langchain_digest
  • src/domain_agent/adapters/outbound/langchain.py

핵심 wiring:

from domain_agent.adapters.outbound import LangChainAgentEngine

dependencies = WorkflowDependencies(
    context_provider=LangChainDigestContextProvider(),
    agent_engine=LangChainAgentEngine(
        model=my_langchain_model,
        tools=my_langchain_tools,
        prepared_by="langchain-agent",
    ),
    action_executor=my_action_executor,
    requires_human_review=False,
)

중요한 점:

  • LangChain tool list는 planning validation에 사용됩니다
  • 실제 실행은 ActionExecutor가 담당합니다
  • 즉 LangChain은 "무엇을 할지"를 만들고, executor는 "어떻게 실행할지"를 담당합니다

Recipe 4: Move From Fake To Real Integrations

처음부터 실제 provider를 붙일 필요는 없습니다.

추천 전환 순서:

  1. deterministic AgentEngine
  2. fake/replayable LangChain runnable
  3. real LangChain model adapter
  4. real repository / real executor / real review UI

이 순서가 좋은 이유:

  • domain invariants를 먼저 고정할 수 있음
  • 테스트가 깨지지 않음
  • failure surface를 단계적으로 넓힐 수 있음

실제로 교체되는 지점은 많지 않습니다.

교체 대상:

  • ContextProvider
  • AgentEngine
  • ActionExecutor
  • optional review_handler

고정되는 것:

  • Request
  • AgentPlan
  • ReviewPacket
  • PlanReviewResult
  • LangGraph workflow shape

Practical Starting Points

가장 추천하는 시작 패턴:

  1. domain 모델 작성
  2. deterministic AgentEngine으로 first pass
  3. autonomous mode로 end-to-end 연결
  4. review가 필요하면 requires_human_review=True
  5. LLM이 필요해지면 LangChainAgentEngine으로 교체

즉 이 템플릿은 "처음부터 LangChain agent를 강하게 넣는다"보다 "DDD 경계를 먼저 잡고, 필요해질 때 LangChain을 AgentEngine에 끼운다"는 흐름에 더 잘 맞습니다.

Code References

  • src/domain_agent/adapters/inbound/cli_demo.py
  • examples/streamlit_review_demo/streamlit_review_demo/app.py
  • src/domain_agent/application/use_cases.py
  • src/domain_agent/orchestration/langgraph/graph.py
  • src/domain_agent/orchestration/langgraph/nodes/deterministic.py
  • src/domain_agent/adapters/outbound/langchain.py
  • examples/autonomous_digest
  • examples/langchain_digest
  • examples/github_repo_review
  • examples/operational_change
  • examples/mock_api