AI·News
뒤로

딥 에이전트, LangSmith, 병렬 처리를 사용한 회사 실사 에이전트 구축

https://www.langchain.com/blog/building-a-company-due-diligence-agent-with-deep-agents-langsmith-and-parallel

에이전트 오케스트레이션과 구조화된 웹 인텔리전스를 활용한 다단계 기업 조사 자동화

기업 실사(Due Diligence)는 금융 서비스 전반에서 나타나는 워크플로우입니다. PE 분석가들은 딜을 심사하고, 은행 신용팀은 차용자를 평가하며, 컴플라이언스팀은 새로운 실체를 온보딩하고, 보험 인수팀은 상업용 보험 계약자를 평가합니다. 이 리서치는 일관된 패턴을 따릅니다. 기업을 선택하고 여러 차원에서 조사한 후 모든 주장에 출처 추적이 있는 구조화된 인텔리전스 보고서를 작성합니다.

이 쿡북은 LangChain의 Deep AgentsParallel's Task API를 결합하여 이 워크플로우를 자동화하는 에이전트를 구축합니다. Deep Agents는 계획, 서브에이전트 위임, 컨텍스트 관리를 처리합니다. Parallel은 실제 리서치를 처리하며, Basis를 통해 필드별 인용, 추론 추적 및 보정된 신뢰도 점수를 포함한 구조화된 결과를 반환합니다. 한 트랙의 결과가 새로운 질문을 제기할 때, Parallel의 대화형 리서치 기능을 통해 에이전트는 이전 리서치 스레드의 모든 컨텍스트와 함께 후속 질문을 연쇄할 수 있습니다.

개요

에이전트는 5개의 리서치 트랙을 오케스트레이션하며, 각각 전담 서브에이전트가 처리합니다:

  • 기업 프로필 — 법적 실체 구조, 주요 임원, 설립 이력, 직원 수, 사무소 위치
  • 재무 건전성 — 펀딩 이력, 수익 신호, 밸류에이션 지표, 수익성 마커
  • 소송 및 규제 — 소송, SEC 제출 서류, 제재 심사, 규제 조치, 합의
  • 뉴스 및 평판 — 최근 언론 보도, 리더십 변화, 논란 플래그, 미디어 감정
  • 경쟁 구도 — 상위 3개 직접 경쟁사를 식별하고 목표의 포지셔닝 파악

competitive-landscape가 명명된 목록을 반환한 후, 오케스트레이터는 경쟁사당 하나씩 별도의 competitor-analysis 서브에이전트를 병렬로 배포합니다. 이는 정표적인 Deep Agents 팬아웃 형태로, 각 인스턴스는 자체 격리된 컨텍스트에서 실행됩니다. 오케스트레이터는 그 후 모든 워크페이퍼를 읽고 모순과 낮은 신뢰도 결과를 교차 참조하며, 불일치가 나타날 때 Parallel의 Search API를 통해 임시 조회를 실행하고, 리스크 플래그와 인용 추적이 있는 최종 보고서를 작성합니다.

실사는 이 다단계 아키텍처가 필요한 이유는 이전 결과가 다음에 조사해야 할 대상을 변경하기 때문입니다. 기업 프로필에서 목표가 자회사임이 드러나면, 재무 분석은 모회사를 포함해야 합니다. 소송 스캔에서 SEC 조사가 나타나면, 리스크 평가가 변경됩니다. Deep Agents의 계획 도구를 통해 오케스트레이터는 결과가 리서치 계획을 변경할 때 적응할 수 있습니다.

각 리서치 트랙은 pro-fast 프로세서 Task API 호출을 사용합니다. Rivian Automotive (NASDAQ: RIVN)에서 엔드-투-엔드 검증됨: 약 23분 내 9개 호출. 현재 요금은 Parallel 가격 책정을 참조하세요.

구현

uv pip install deepagents langchain-parallel langchain-anthropic
export ANTHROPIC_API_KEY="your-anthropic-api-key"
export PARALLEL_API_KEY="your-parallel-api-key"

Parallel 리서치 도구 정의

두 가지 도구를 정의합니다. 첫 번째는 Basis 인식 신뢰도 처리를 포함한 구조화된 리서치를 위해 Parallel의 Task API를 래핑합니다. 두 번째는 LangChain 통합의 웹 검색 도구를 사용하여 합성 중 빠른 사실 조회를 수행합니다.

from typing import Optional

from langchain_core.tools import tool
from langchain_parallel import (
    ParallelTaskRunTool,
    ParallelWebSearchTool,
    parse_basis,
)


@tool
def research_task(
    query: str,
    output_description: str,
    previous_interaction_id: Optional[str] = None,
) -> dict:
    """Parallel의 Task API를 통해 구조화된 웹 리서치를 실행합니다.

    필드별 인용과 신뢰도 점수(Basis)를 포함한 결과를 반환합니다.
    previous_interaction_id를 사용하여 이전 리서치 컨텍스트를 기반으로 하는
    후속 질문을 연쇄합니다.
    """
    runner = ParallelTaskRunTool(
        processor="pro-fast",
        task_output_schema=output_description,
    )
    invoke_args: dict = {"input": query}
    if previous_interaction_id:
        invoke_args["previous_interaction_id"] = previous_interaction_id

    result = runner.invoke(invoke_args)
    parsed = parse_basis(result)

    output = result["output"]
    findings = output.get("content") if isinstance(output, dict) else output

    response: dict = {
        "findings": findings,
        "citations_by_field": parsed["citations_by_field"],
        "interaction_id": parsed["interaction_id"],
    }
    if parsed["low_confidence_fields"]:
        response["low_confidence_warning"] = (
            "These fields came back with low confidence and should be "
            "verified, ideally by chaining a follow-up query with "
            "previous_interaction_id: "
            + ", ".join(parsed["low_confidence_fields"])
        )
    return response


# 합성 중 빠른 사실 조회를 위한 빠른 검색 도구
quick_search = ParallelWebSearchTool()

이 도구는 원본 API 호출 이상으로 세 가지를 수행합니다. parse_basis(result)를 호출하여 필드별 인용과 낮은 신뢰도 필드의 이름을 추출합니다. 이를 도구의 반환 값에 명시적 low_confidence_warning으로 표시하므로, 호출하는 서브에이전트의 추론 루프는 후속을 연쇄할 필요가 있는지 결정할 수 있습니다. 그리고 interaction_id를 반환하므로 연쇄된 호출이 previous_interaction_id를 통해 동일한 리서치 스레드에 앵커될 수 있습니다.

리서치 서브에이전트 정의

각 리서치 트랙은 특화된 시스템 프롬프트와 research_task 도구에 대한 접근을 갖춘 자체 서브에이전트를 얻습니다.

corporate_profile_subagent = {
    "name": "corporate-profile",
    "description": "기업 구조, 리더십, 설립 이력 및 직원 수 리서치",
    "system_prompt": """당신은 기업 리서치 분석가입니다.

주어진 기업에 대해 research_task 도구를 사용하여 다음을 찾습니다:
- 법적 실체명, 설립 주/국가, 설립 날짜
- 현재 CEO 및 주요 임원진(이름, 직함, 대략적 재임 기간)
- 본사 위치 및 주요 사무소 위치
- 직원 수(현재 및 최근 추세)
- 기업 구조(모회사, 주요 자회사)

output_description 매개변수에 대해 이들을 구조화된 필드로 요청합니다.

결과에 low_confidence_warning이 포함되어 있으면, 반환된 interaction_id를
사용하여 플래그된 필드를 확인하는 후속 질문을 연쇄합니다.

결과(citations_by_field 포함)를 corporate-profile.md에 작성합니다.""",
    "tools": [research_task],
}

다른 Phase-1 서브에이전트(financial-health, litigation-regulatory, news-reputation, competitive-landscape)는 자체 초점화된 프롬프트와 함께 동일한 형태를 따릅니다. 전체 집합은 agent.py에 있습니다.

Phase-2 팬아웃 서브에이전트는 competitive-landscape로 식별된 경쟁사당 한 번씩 호출됩니다:

competitor_analysis_subagent = {
    "name": "competitor-analysis",
    "description": "명명된 한 경쟁사의 초점화된 프로필 생성",
    "system_prompt": """당신은 경쟁 인텔리전스 리서처입니다.

오케스트레이터는 단일 경쟁사명과 원래 실사 목표를 전달합니다.
다음을 요청하는 하나의 research_task 호출을 수행합니다:
- 기업 스냅샷(본사, 상장/비상장, 직원 수, 설립 연도)
- 가장 최근의 수익 및 성장 신호
- 펀딩 또는 시가총액 상태
- 원래 실사 목표 대비 제품/포지셔닝
- 지난 12개월의 최근 전략적 움직임
- 목표 대비 주목할만한 강점 및 약점

결과를 competitor-<slug>.md에 작성합니다.""",
    "tools": [research_task],
} 

오케스트레이터 에이전트 생성

메인 에이전트는 서브에이전트를 조율하고, 모순에 대해 결과를 검토하고, 최종 보고서를 생성합니다. 우리는 FilesystemBackend으로 이를 지원하므로 워크페이퍼와 최종 메모가 에이전트 상태와 함께 소멸하기보다는 ./reports/ 아래 디스크에 지속됩니다.

from pathlib import Path

from deepagents import create_deep_agent
from deepagents.backends.filesystem import FilesystemBackend

REPORTS_DIR = Path("./reports")
REPORTS_DIR.mkdir(parents=True, exist_ok=True)

diligence_instructions = """\
당신은 전문화된 리서처 팀을 관리하는 시니어 실사 분석가입니다. 당신의 일은
검증 가능한 주장을 포함한 종합적인 기업 인텔리전스 보고서를 생성하는
것입니다.

## 당신의 프로세스

1. **리서치 계획**: write_todos를 사용하여 실사를 체크리스트로 설정합니다.
   Phase 1은 5개의 Phase-1 서브에이전트를 배포합니다. Phase 2는
   competitive-landscape로 식별된 경쟁사당 하나의 competitor-analysis
   서브에이전트를 배포합니다.

2. **Phase 1 — 병렬 리서치**: task 도구를 사용하여 corporate-profile,
   financial-health, litigation-regulatory, news-reputation,
   competitive-landscape를 동시에 배포합니다.

3. **Phase 2 — 경쟁사 팬아웃**: competitive-landscape.md를 읽고
   명명된 3개 경쟁사를 파싱합니다. 경쟁사당 별도의
   competitor-analysis 서브에이전트 인스턴스를 병렬로 배포합니다.

4. **검토 및 교차 참조**: 모든 워크페이퍼를 읽습니다. 모순, 낮은 신뢰도
   결과 및 격차를 찾습니다. 합성 중 임시 조회를 위해 quick_search를
   사용합니다.

5. **보고서 합성**: 이사회 요약, 기업 프로필, 재무 개요, 소송 및 규제
   리스크 평가, 뉴스 및 평판 분석, 경쟁 구도(경쟁사별 부분 포함),
   신뢰도 및 검증 노트, 주요 리스크 플래그 포함

## 인용 및 신뢰도 지침

- 주요 주장에 대한 출처 URL을 포함합니다.
- 신뢰도가 낮은 결과를 호출합니다. 이들은 인간 검증이 필요합니다.
- 두 트랙이 모순된 정보를 생성한 경우, 양쪽 출처의 인용과 함께
  불일치를 명시적으로 기록합니다.
"""

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[quick_search],
    subagents=[
        corporate_profile_subagent,
        financial_health_subagent,
        litigation_subagent,
        news_reputation_subagent,
        competitive_landscape_subagent,
        competitor_analysis_subagent,
    ],
    system_prompt=diligence_instructions,
    backend=FilesystemBackend(root_dir=REPORTS_DIR, virtual_mode=True),
)

에이전트 실행

result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Rivian Automotive에 대한 전체 실사 보고서를 실시합니다",
    }]
})

print(result["messages"][-1].content)

스트리밍 실행 진행

오래 걸리는 실사 실행의 경우, 에이전트의 진행을 스트리밍하여 계획, 도구 호출 및 서브에이전트 활동을 실시간으로 확인할 수 있습니다. 서브에이전트 실행 내부의 이벤트를 수신하려면 subgraphs=True를 전달합니다.

for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "Rivian Automotive에 대한 전체 실사 보고서를 실시합니다"}]},
    stream_mode="updates",
    subgraphs=True,
    version="v2",
):
    if chunk.get("type") == "updates":
        source = f"[subagent: {chunk['ns']}]" if chunk.get("ns") else "[orchestrator]"
        print(f"{source} {chunk.get('data')}")

LangSmith를 이용한 관찰 가능성

왜 FSI에서 관찰 가능성이 중요한가

FSI에서 규제 기관, 감사자 및 리스크 팀은 점점 더 기업들이 AI 보조 출력이 어떻게 생성되었는지를 재구성하기를 기대하고 있으며, 특히 그러한 출력이 물질적 비즈니스 결정에 영향을 미칠 때 더욱 그렇습니다. 지금부터 6개월 후, 내부 감사자, 컴플라이언스 검토자, 모델 리스크팀, 투자 위원회 또는 규제 기관이 AI 보조 실사 메모가 어떻게 생성되었는지 물어볼 수 있습니다. 어떤 출처가 각 물질적 결론에 영향을 미쳤습니까? 어떤 신뢰도가 첨부되었습니까? 인간 검토 또는 출력 재정의는 어디서 발생했습니까? 에이전트의 프로세스가 충분히 잘 로깅되어 재구성 가능합니까? FSI에서 "에이전트가 답을 주었어"는 방어 가능한 통제 태세가 아닙니다.

에이전트는 비결정론을 복합하고(LLM 출력, 프롬프트 민감도, 오픈 웹), 실제 웹 리서치에 실제 비용을 소비하며, 규제 기관이 결국 감사할 수 있는 메모로 끝납니다. 모든 주장은 명시적 신뢰도 레이블이 있는 기본 출처로 다시 매핑되어야 하며, 그 매핑은 실행이 완료된 후 수개월간 감사 가능하게 유지되어야 합니다. 에이전트가 프로덕션에 도달하면 대부분의 장애는 거기서 표면화되며, 사전 출시 테스트는 거의 포착하지 못합니다. 추적은 실행이 완료된 후에도 남아있는 산출물입니다.

이것이 FSI에서 추적이 중요한 이유입니다:

  • 로깅이 점점 더 의무화되고 있습니다. EU AI 법안은 고위험 AI 시스템에 대한 자동 이벤트 로깅을 요구하며, 미국 은행 규제 기관은 공식적 범위가 불명확한 경우에도 실제로 AI 에이전트에 모델 리스크 관리 기대를 적용합니다. 추적은 두 프레임워크 모두 고려하는 산출물입니다.
  • 결정 설명 가능성은 청구별 근거 필요합니다. AI 입력이 소비자 신용, 투자 조언 또는 수탁 의무의 대상인 모든 프로세스와 같은 규제 결정에 영향을 미칠 때, 기관은 해당 입력이 어떻게 형성되었는지 설명해야 합니다. Basis 페이로드(소스 URL 및 출력별 신뢰도)는 그 설명을 실행 수개월 후에도 재현 가능하게 만드는 것입니다.
  • 제3자 AI는 지속적인 감독이 필요합니다. 스택은 외부 모델 제공자와 외부 리서치 API(Parallel)를 사용합니다. 추적은 각 제공자에게 전송된 것, 되돌려 받은 것, 최종 메모에 미친 영향을 기록하여 문제 조사 및 공급업체 감독을 지원합니다.
  • 운영 복원력은 빠른 근본 원인 분석에 달려 있습니다. 에이전트 장애가 물질적 운영 중단이나 보고 가능한 ICT 사고에 기여하면, 추적은 팀이 재구성, 개선 및 보고를 위한 구체적인 시작점을 제공합니다.

컴플라이언스 및 감사가 현재 어떻게 작동하는지

FSI 팀은 리서치 메모가 어떻게 생성되었는지 증명하기 위한 시스템을 이미 가지고 있습니다: 분석가 워크페이퍼, 인용 목록, 출처 승인, 버전 이력 및 컴플라이언스 검토입니다. 그 모델은 분석가가 책임 단위이기 때문에 작동합니다. 검사자, 감사자 또는 컴플라이언스 검토자가 결론에 어떻게 도달했는지 물어볼 때, 분석가는 워크페이퍼와 최종 산출물을 뒷받침하는 인용과 함께 추론을 설명할 수 있습니다. AI 에이전트는 그 모델을 변경합니다.

"분석가"는 더 이상 단순히 사람이 아닙니다. 이는 LLM 호출, 도구 호출, 검색된 출처, 중간 출력 및 상태 전환의 그래프입니다. 이러한 단계가 런타임에 캡처되지 않으면, 최종 메모는 남아있을 수 있지만 그것을 생성한 프로세스는 로그, 컨텍스트 창 및 나중에 재구성하기 어려운 공급업체 호출로 사라질 수 있습니다. 추적은 부착 지점을 복원합니다. 그것은 기계 측면 워크페이퍼가 됩니다: 어떤 출처가 각 물질적 결론에 영향을 미쳤는지, 어떤 신뢰도가 첨부되었는지, 어떤 도구가 호출되었는지, 인간 검토가 어디서 발생했는지, 최종 출력이 어떻게 생성되었는지에 대한 검사 가능한 기록입니다.

LangSmith가 캡처하는 것

LangSmith는 에이전트 코드에 변경 없이 이 에이전트의 모든 Deep Agents 단계와 모든 ParallelTaskRunTool 호출을 기록합니다: 서브에이전트가 구성한 프롬프트, Parallel이 반환한 URL, 신뢰도가 있는 Basis 페이로드 및 구조화된 결과입니다. 각 실행은 모든 모델 호출, 도구 호출 및 서브에이전트 전체에 걸쳐 노드별 비용으로도 분해되므로 어떤 단계가 토큰과 시간의 어떤 몫을 주도했는지 정확히 볼 수 있습니다. 두 개의 실행이 매우 다른 비용으로 돌아올 때, 추적은 차이가 서브에이전트 추론, 추가 Parallel 호출 또는 최종 합성 통과에 있는지 보여줍니다.

추적이 보여주는 것

모든 실행을 열면 가장 먼저 보이는 것은 오케스트레이터의 계획입니다: 모든 서브에이전트가 실행되기 전에 리서치 전략을 설정하는 4단계 TODO입니다.

실행 시작에 write_todos로 생성된 오케스트레이터의 4단계 계획

Phase 1은 모든 5개 리서치 서브에이전트를 병렬로 배포합니다: corporate-profile, financial-health, litigation-regulatory, news-reputation, competitive-landscape. 각 서브에이전트는 발송 도구 호출에서 일반 영어로 설명되는 초점화된 미션을 받습니다. 추적의 이러한 task 노드 중 하나를 클릭하면 그 서브에이전트가 정확히 무엇을 하고 있는지 볼 수 있습니다: 발급한 프롬프트, 수행한 Parallel 호출 및 돌아온 출처입니다.

Phase 1 팬아웃: 병렬로 배포된 5개 리서치 서브에이전트

Phase 1이 완료된 후, 오케스트레이터는 경쟁사별 분석(Phase 2)을 팬아웃하고, 모순에 대해 워크페이퍼를 교차 참조하고(Phase 3), 최종 메모를 합성합니다(Phase 4). 모든 도구 호출이 그 과정에서 캡처됩니다.

서브에이전트의 research_task를 선택하면 Parallel이 반환한 전체 구조화된 결과가 표시됩니다: 모든 필드, 모든 발췌문 및 모든 URL로 워크페이퍼에 도달하는 요약을 포함한 콘텐츠를 초과합니다.

서브에이전트의 research_task 출력: Parallel이 반환한 구조화된 결과

인용 및 신뢰도

컴플라이언스 검토자의 경우, 관련 보기는 parallel_task_run 내부의 Basis 페이로드입니다. Parallel은 각 출력을 소스 URL, 신뢰도 레이블(높음/중간/낮음) 및 답변이 어떻게 조립되었는지 설명하는 한 줄의 추론 추적과 함께 첨부합니다.

Basis 페이로드: 소스 URL, 신뢰도 레이블 및 추론 추적

위에 표시된 Rivian corporate-profile 호출에서, 에이전트의 medium 신뢰도 출력은 4개의 출처에 근거합니다: Rivian의 10-K 및 2026 연차 보고서(SEC.gov), 2026 위임장의 제3자 재현 및 Wikipedia입니다. 2개의 기본 SEC 제출 서류, 1개의 2차 재현 및 1개의 3차 출처의 혼합은 컴플라이언스 검토자가 플래그하기를 원하는 근거 패턴입니다. 추적으로, 근거는 청구별로 검사 가능하며, 이와 같은 소싱 패턴은 실행 전체에서 수정 가능해집니다. 이 레이어 없는 워크페이퍼는 동일한 4개 URL을 평면으로 나열하며, 어떤 URL이 기본인지에 대한 신호가 없습니다.

단일 추적을 초월하여

하나의 실사 메모의 경우, 추적은 감시 추적입니다. 분기 동안 실행된 메모 포트폴리오의 경우, 패턴 발견도 필요합니다: 어떤 서브에이전트가 가장 낮은 신뢰도 출력을 생성하고, 어떤 목표가 가장 많은 연쇄된 Parallel 후속을 강요하고, 어떤 출처가 더 얇은 콘텐츠를 반환하기 시작했습니까. LangSmith는 정확히 그 기능을 위한 교차 실행 분석을 통해 추적 기반 위에 구축합니다. 규모로 실사를 실행하는 FSI 팀의 경우, 그 기능은 감사 추적을 운영 규율로 변환합니다.

누구를 위한 것인가

이 아키텍처는 거래 심사, 신용 인수, KYB/KYC 온보딩, M&A 목표 평가 및 공급업체 리스크 평가를 포함한 기업에 대한 구조화된 리서치 워크플로우를 실행하는 모든 팀에 적용됩니다.

여기의 5개 리서치 트랙은 시작점입니다. 워크플로우와 관련된 트랙으로 교체합니다: 컴플라이언스 집약적 실사를 위해 경영진 배경 검사 및 최종 소유권 추적을 추가하고, M&A 심사를 위해 IP 포트폴리오 분석을 추가하고, 공급업체 평가를 위해 SOC 2 검증을 추가합니다. 각 추가 트랙은 시스템 프롬프트와 동일한 research_task 도구를 갖춘 새로운 서브에이전트 dict입니다.

리소스

Automate multi-step company research with agentic orchestration and structured web intelligence.

Company due diligence is a workflow that shows up everywhere in financial services. PE analysts screen deals, bank credit teams assess borrowers, compliance teams onboard new entities, insurance underwriters evaluate commercial policyholders. The research follows a consistent pattern. Take a company, investigate it across several dimensions, produce a structured intelligence report where every claim has a source trail.

This cookbook builds an agent that automates that workflow by combining LangChain's Deep Agents for orchestration and Parallel's Task API for web research. Deep Agents handles planning, subagent delegation, and context management. Parallel handles the actual research, returning structured findings with per-field citations, reasoning traces, and calibrated confidence scores via Basis. When findings from one track raise new questions, Parallel's interactive research feature lets the agent chain follow-up queries with full context from the prior research thread.

Overview

The agent orchestrates five research tracks, each handled by a dedicated subagent:

  • Corporate profile — legal entity structure, key officers, founding history, headcount, office locations
  • Financial health — funding history, revenue signals, valuation indicators, profitability markers
  • Litigation and regulatory — lawsuits, SEC filings, sanctions screening, regulatory actions, settlements
  • News and reputation — recent press coverage, leadership changes, controversy flags, media sentiment
  • Competitive landscape — identifies the top three direct competitors and the target's positioning

Once competitive-landscape returns its named list, the orchestrator dispatches a separate competitor-analysis subagent once per competitor, in parallel — the canonical Deep Agents fan-out shape, with each instance running in its own isolated context. The orchestrator then reads every workpaper, cross-references for contradictions and low-confidence findings, runs ad-hoc lookups via Parallel's Search API when discrepancies surface, and writes the final report with risk flags and citation trails.

DD requires this multi-step architecture because earlier findings change what needs to be investigated next. If the corporate profile reveals the target is a subsidiary, the financial analysis needs to cover the parent. If the litigation scan surfaces an SEC investigation, the risk assessment changes. Deep Agents' planning tool lets the orchestrator adapt when findings shift the research plan.

Each research track uses a pro-fast processor Task API call. Validated end-to-end on Rivian Automotive (NASDAQ: RIVN): nine calls in ~23 minutes. See Parallel pricing for current rates.

Implementation

uv pip install deepagents langchain-parallel langchain-anthropic
export ANTHROPIC_API_KEY="your-anthropic-api-key"
export PARALLEL_API_KEY="your-parallel-api-key"

Defining the Parallel research tools

We define two tools. The first wraps Parallel's Task API for structured research with Basis-aware confidence handling. The second uses the LangChain integration's web search tool for quick factual lookups during synthesis.

from typing import Optional

from langchain_core.tools import tool
from langchain_parallel import (
    ParallelTaskRunTool,
    ParallelWebSearchTool,
    parse_basis,
)


@tool
def research_task(
    query: str,
    output_description: str,
    previous_interaction_id: Optional[str] = None,
) -> dict:
    """Run structured web research via Parallel's Task API.

    Returns findings with per-field citations and confidence scores (Basis).
    Use previous_interaction_id to chain follow-up queries that build on
    prior research context.
    """
    runner = ParallelTaskRunTool(
        processor="pro-fast",
        task_output_schema=output_description,
    )
    invoke_args: dict = {"input": query}
    if previous_interaction_id:
        invoke_args["previous_interaction_id"] = previous_interaction_id

    result = runner.invoke(invoke_args)
    parsed = parse_basis(result)

    output = result["output"]
    findings = output.get("content") if isinstance(output, dict) else output

    response: dict = {
        "findings": findings,
        "citations_by_field": parsed["citations_by_field"],
        "interaction_id": parsed["interaction_id"],
    }
    if parsed["low_confidence_fields"]:
        response["low_confidence_warning"] = (
            "These fields came back with low confidence and should be "
            "verified, ideally by chaining a follow-up query with "
            "previous_interaction_id: "
            + ", ".join(parsed["low_confidence_fields"])
        )
    return response


# Quick search tool for fast factual lookups during synthesis
quick_search = ParallelWebSearchTool()

The tool does three things beyond a raw API call. It calls parse_basis(result) to extract per-field citations and the names of any low-confidence fields. It surfaces those names as an explicit low_confidence_warning in the tool's return value, so the calling subagent's reasoning loop can decide to chain a follow-up. And it returns the interaction_id so the chained call can anchor to the same research thread via previous_interaction_id.

Defining the research subagents

Each research track gets its own subagent with a specialized system prompt and access to the research_task tool.

corporate_profile_subagent = {
    "name": "corporate-profile",
    "description": "Research corporate structure, leadership, founding history, and headcount",
    "system_prompt": """You are a corporate research analyst.

Given a company, use the research_task tool to find:
- Legal entity name, incorporation state/country, founding date
- Current CEO and key executives (names, titles, approximate tenure)
- Headquarters location and major office locations
- Employee headcount (current and recent trend)
- Corporate structure (parent company, major subsidiaries)

For the output_description parameter, request these as structured fields.

If the result includes a low_confidence_warning, chain a follow-up query
using the returned interaction_id to verify the flagged fields.

Write your findings (including citations_by_field) to corporate-profile.md.""",
    "tools": [research_task],
}

The other Phase-1 subagents (financial-health, litigation-regulatory, news-reputation, competitive-landscape) follow the same shape with their own focused prompts. The full set is in agent.py.

The Phase-2 fan-out subagent is invoked once per competitor identified by competitive-landscape:

competitor_analysis_subagent = {
    "name": "competitor-analysis",
    "description": "Produce a focused profile of one named competitor",
    "system_prompt": """You are a competitive intelligence researcher.

The orchestrator will pass you a single competitor name and the original
DD target. Make one research_task call requesting:
- Corporate snapshot (HQ, public/private, headcount, founding year)
- Most recent revenue and growth signals
- Funding or market cap status
- Product / positioning vs. the original DD target
- Recent strategic moves in the last 12 months
- Notable strengths and weaknesses relative to the target

Write your findings to competitor-<slug>.md.""",
    "tools": [research_task],
} 

Creating the orchestrator agent

The main agent coordinates the subagents, reviews findings for contradictions, and produces the final report. We back it with a FilesystemBackend so workpapers and the final memo persist to disk under ./reports/ rather than evaporating with the agent state.

from pathlib import Path

from deepagents import create_deep_agent
from deepagents.backends.filesystem import FilesystemBackend

REPORTS_DIR = Path("./reports")
REPORTS_DIR.mkdir(parents=True, exist_ok=True)

diligence_instructions = """\
You are a senior due diligence analyst managing a team of specialized
researchers. Your job is to produce a comprehensive company intelligence
report with verifiable claims.

## Your Process

1. **Plan the research**: Use write_todos to lay out the diligence as a
   checklist. Phase 1 dispatches the five Phase-1 subagents. Phase 2
   dispatches one competitor-analysis subagent per competitor identified
   by competitive-landscape.

2. **Phase 1 — parallel research**: Use the task tool to dispatch
   corporate-profile, financial-health, litigation-regulatory,
   news-reputation, and competitive-landscape concurrently.

3. **Phase 2 — competitor fan-out**: Read competitive-landscape.md and
   parse the three named competitors. Dispatch a separate
   competitor-analysis subagent instance per competitor, in parallel.

4. **Review and cross-reference**: Read every workpaper. Look for
   contradictions, low-confidence findings, and gaps. Use quick_search
   for ad-hoc lookups during synthesis.

5. **Synthesize the report** with: executive summary, corporate profile,
   financial overview, litigation and regulatory risk assessment, news
   and reputation analysis, competitive landscape (with per-competitor
   sub-sections), confidence and verification notes, and key risk flags.

## Citation and Confidence Guidelines

- Include source URLs for key claims.
- Call out any finding where confidence was low. These need human verification.
- If two tracks produced contradictory information, note the discrepancy
  explicitly with citations from both sources.
"""

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[quick_search],
    subagents=[
        corporate_profile_subagent,
        financial_health_subagent,
        litigation_subagent,
        news_reputation_subagent,
        competitive_landscape_subagent,
        competitor_analysis_subagent,
    ],
    system_prompt=diligence_instructions,
    backend=FilesystemBackend(root_dir=REPORTS_DIR, virtual_mode=True),
)

Running the agent

result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Conduct a full due diligence report on Rivian Automotive",
    }]
})

print(result["messages"][-1].content)

Streaming execution progress

For long-running diligence runs, stream the agent's progress to see planning, tool calls, and subagent activity in real time. Pass subgraphs=True to receive events from inside subagent execution.

for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "Conduct a full due diligence report on Rivian Automotive"}]},
    stream_mode="updates",
    subgraphs=True,
    version="v2",
):
    if chunk.get("type") == "updates":
        source = f"[subagent: {chunk['ns']}]" if chunk.get("ns") else "[orchestrator]"
        print(f"{source} {chunk.get('data')}")

Observability with LangSmith

Why observability matters for FSI

In FSI, regulators, auditors, and risk teams increasingly expect firms to reconstruct how AI-assisted outputs were produced, especially when those outputs influence material business decisions. Six months from now, an internal auditor, compliance reviewer, model-risk team, investment committee, or regulator may ask how an AI-assisted diligence memo was produced. Which sources informed each material conclusion? What confidence was attached? Where did a human review or override the output? Was the agent’s process logged well enough to reconstruct? In FSI, “the agent gave me an answer” is not a defensible control posture.

The agent compounds non-determinism (LLM output, prompt sensitivity, the open web), spends real money on real web research, and ends in a memo a regulator may eventually audit. Every claim has to map back to a primary source with an explicit confidence label, and that mapping has to remain auditable months after the run finishes. Once the agent reaches production, most of its failures surface there too, where pre-launch testing rarely catches them. The trace is the artifact that survives the run.

This is why the trace matters in FSI specifically:

  • Logging is increasingly mandated. The EU AI Act requires automatic event logging for high-risk AI systems, and US bank regulators apply model risk management expectations to AI agents in practice even where formal scope is unsettled. The trace is the artifact both frameworks contemplate.
  • Decision explainability requires per-claim grounding. When AI input feeds a regulated decision such as consumer credit, investment recommendations, or any process subject to fiduciary obligations, the institution has to explain how that input was formed. The basis payload (source URLs and per-output confidence) is what makes that explanation reproducible months after the run.
  • Third-party AI requires ongoing supervision. The stack uses an external model provider and an external research API (Parallel). A trace records what was sent to each provider, what came back, and how those outputs influenced the final memo, supporting issue investigation and vendor oversight.
  • Operational resilience depends on fast root-cause analysis. If an agent failure contributes to a material operational disruption or reportable ICT incident, the trace gives teams a concrete starting point for reconstruction, remediation, and reporting.

How compliance and audit work today

FSI teams already have a system for proving how a research memo was produced: analyst workpapers, citation lists, source approvals, version history, and compliance review. That model works because the analyst is the unit of accountability. When an examiner, auditor, or compliance reviewer asks how a conclusion was reached, the analyst can walk through the reasoning, with workpapers and citations backing up the final deliverable. AI agents change that model.

The “analyst” is no longer just a person. It is a graph of LLM calls, tool invocations, retrieved sources, intermediate outputs, and state transitions. Unless those steps are captured at runtime, the final memo may survive, but the process that produced it can disappear into logs, context windows, and vendor calls that are difficult to reconstruct later. The trace restores the attach point. It becomes the machine-side workpaper: an inspectable record of which sources informed each material conclusion, what confidence was attached, which tools were called, where human review occurred, and how the final output was produced.

What LangSmith captures

LangSmith records every Deep Agents step and every ParallelTaskRunTool invocation in this agent: the prompt the subagent constructed, the URLs Parallel returned, the basis payload with confidence, and the structured findings, with no changes to the agent code. Each run is also broken down into per-node cost across every model call, tool call, and subagent, so you can see exactly which step drove which share of tokens and time. When two runs come back at very different cost, the trace shows whether the difference lives in subagent reasoning, additional Parallel calls, or the final synthesis pass.

What the trace shows

Open any run and the first thing you see is the orchestrator's plan: a four-phase TODO that lays out the research strategy before any subagent runs.

Orchestrator's four-phase plan, generated by write_todos at the start of the run.

Phase 1 then dispatches all five research subagents in parallel: corporate-profile, financial-health, litigation-regulatory, news-reputation, and competitive-landscape. Each subagent receives a focused mission described in plain English in the dispatch tool call. Click into any of those task nodes in the trace and you can see exactly what that subagent is doing: the prompt it issued, the Parallel calls it made, and the sources that came back.

Phase 1 fan-out: five research subagents dispatched in parallel.

After Phase 1 completes, the orchestrator fans out per-competitor analyses (Phase 2), cross-references workpapers for contradictions (Phase 3), and synthesizes the final memo (Phase 4). Every tool call is captured along the way.

Selecting any subagent's research_task shows the full structured findings Parallel returned: every field, every excerpt, and every URL, including content beyond the summary that lands in the workpaper.

A subagent's research_task output: structured findings returned by Parallel.

Citations and confidence

For a compliance reviewer, the relevant view is the basis payload inside parallel_task_run. Parallel attaches each output with source URLs, a confidence label (high / medium / low), and a one-line reasoning trace explaining how the answer was assembled.

Basis payload: source URLs, confidence label, and reasoning trace.

In the Rivian corporate-profile call shown above, the agent's medium-confidence output is grounded in four sources: Rivian's 10-K and 2026 annual report on SEC.gov, a third-party reproduction of the 2026 proxy statement, and Wikipedia. That mix of two primary SEC filings, one secondary reproduction, and one tertiary source is exactly the kind of grounding pattern a compliance reviewer would want to flag. With the trace, the grounding is inspectable per claim, and sourcing patterns like this one become correctable across runs. A workpaper without this layer would list the same four URLs flat, with no signal about which were primary.

Beyond a single trace

For one DD memo, the trace is the audit trail. For a portfolio of memos run across a quarter, you also need pattern discovery: which subagent produces the most low-confidence outputs, which targets force the most chained Parallel follow-ups, which sources have started returning thinner content. LangSmith builds on the trace foundation with cross-run analytics for exactly that. For an FSI team running diligence at scale, that capability turns an audit trail into an operating discipline.

Who this is for

This architecture applies to any team running structured research workflows on companies, including deal screening, credit underwriting, KYB/KYC onboarding, M&A target evaluation, and vendor risk assessment.

The five research tracks here are a starting point. Swap in tracks relevant to your workflow: add management background checks and beneficial ownership tracing for compliance-heavy diligence, add IP portfolio analysis for M&A screening, add SOC 2 verification for vendor assessment. Each additional track is a new subagent dict with a system prompt and the same research_task tool.

Resources

원문 보기 https://www.langchain.com/blog/building-a-company-due-diligence-agent-with-deep-agents-langsmith-and-parallel