NLWeb discovery는 “사용자의 자연어 요청을 처리할 수 있는 웹사이트, 에이전트, MCP tool, A2A agent, OpenAPI 서비스, skill 등을 어떻게 발견하고 선택할 것인가”에 대한 계층입니다. NLWeb 자체는 웹사이트가 /ask 같은 자연어 질의 엔드포인트와 MCP 호환 인터페이스를 제공하게 하는 공개 프로젝트이고, Microsoft 설명에 따르면 웹사이트를 AI 앱처럼 질의 가능하게 하며 Schema.org, RSS 같은 기존 구조화 데이터를 활용합니다.

핵심은 **/ask가 “이 사이트에 물어보기”라면, discovery/Who는 “어느 사이트나 도구에 물어볼지 찾기”**입니다. 공식 Who 문서도 Who를 자연어 쿼리에 대해 “처리 가능한 augment를 랭킹해서 반환하는” 단일 주요 operation으로 설명합니다. 여기서 augment는 NLWeb agent뿐 아니라 MCP tool, A2A skill, Claude/Agent skill, OpenAPI, custom HTTP endpoint까지 포함하는 넓은 개념입니다.

전체 흐름

NLWeb discovery는 보통 두 단계로 나뉩니다.

  1. 발견/등록 단계: 사이트나 조직이 “내가 제공하는 에이전트/툴은 이것이다”라는 Agent Manifest를 공개합니다.
  2. 질의/라우팅 단계: Who 서버 또는 AgentFinder가 그 manifest들을 인덱싱해 두었다가, 사용자의 자연어 요청이 들어오면 가장 적합한 augment를 랭킹해 반환합니다. 공식 discovery 문서는 discovery가 /who 프로토콜과 의도적으로 분리되어 있다고 설명합니다. 즉, discovery는 인덱스를 채우는 과정이고, /who는 그 인덱스를 조회하는 과정입니다.

예를 들어 사용자가 “마라톤 훈련용 러닝화를 어디서 살 수 있어?”라고 묻는다면, Who 서버는 신발 쇼핑을 처리할 수 있는 NLWeb agent, 전자상거래 MCP tool, OpenAPI endpoint 등을 찾아 점수와 호출 정보를 반환합니다. AgentFinder README도 /who REST endpoint 예시로 running shoes 질의를 보내면 Nike.com, Adidas.com 같은 결과와 score, description을 반환하는 구조를 보여줍니다.

public web에서의 discovery 메커니즘

공식 discovery 문서는 public web에서 Agent Manifest를 발견하는 방법으로 세 가지를 제안합니다.

첫째, 사이트는 고정 위치에 manifest를 둘 수 있습니다.

https://{domain}/.well-known/agent-manifest.json

둘째, robots.txtAgentmap 지시어를 넣을 수 있습니다.

User-agent: *
Disallow: /private/

Sitemap: https://example.com/sitemap.xml
Agentmap: https://example.com/agents/manifest.json

셋째, HTML에 manifest 링크를 넣을 수 있습니다.

<link rel="agent-manifest" href="https://example.com/agents/manifest.json">

이 방식들은 기존 웹의 robots.txt, sitemap, .well-known 패턴을 따른다는 점이 중요합니다. 즉, AI agent용 새 discovery를 완전히 별도 생태계로 만들기보다, 웹 크롤러와 사이트 운영자가 이미 이해하는 방식에 얹는 설계입니다.

Agent Manifest 구조

Agent Manifest는 사이트가 제공하는 agentic capability를 JSON으로 선언하는 문서입니다. 최상위에는 @context, name, description, url, version, provider, agents 같은 필드가 있고, 각 agent entry에는 protocol, endpoint, definition이 들어갑니다. 공식 문서는 protocol 값으로 nlweb, mcp, a2a, openapi, skill, http를 예시합니다.

간단한 NLWeb agent manifest 예시는 이런 모양입니다.

{
  "@context": "https://nlweb.ai/schemas/manifest/v0.1",
  "name": "Example Corp Services",
  "description": "Agentic services provided by Example Corp",
  "url": "https://example.com",
  "provider": {
    "name": "Example Corp",
    "url": "https://example.com/about"
  },
  "agents": [
    {
      "protocol": "nlweb",
      "endpoint": "https://recipes.example.com/nlweb",
      "definition": {
        "name": "Recipe Search",
        "description": "Search and browse recipes",
        "capabilities": {
          "streaming": true
        },
        "skills": [
          {
            "name": "recipe_search",
            "description": "Find recipes by ingredients, cuisine, or dietary restrictions",
            "tags": ["recipes", "cooking"],
            "examples": [
              "vegetarian pasta recipes",
              "quick dinner ideas with chicken"
            ]
          }
        ]
      }
    }
  ]
}

중요한 설계 포인트는 definition이 프로토콜별 native format을 보존한다는 점입니다. MCP의 경우 tools/list 결과 형태를 그대로 담고, A2A는 Agent Card를, OpenAPI는 spec URL을, skill은 SKILL.md frontmatter를 JSON화해 넣을 수 있습니다.

/who 요청과 응답

Who 요청은 대체로 querymeta로 구성됩니다. query.text가 필수이고, 선택적으로 type, domain, capabilities로 필터링할 수 있습니다. 예를 들어 type"NLWebAgent""Skill"로 제한하거나, domain"travel", "finance"처럼 줄 수 있습니다. meta.max_results로 반환 개수를 제한할 수도 있습니다.

{
  "query": {
    "text": "I need to find vegetarian Indian recipes",
    "domain": "recipes"
  },
  "meta": {
    "version": "0.1",
    "max_results": 10
  }
}

응답은 NLWeb 관례에 맞춰 _meta와 결과 배열을 포함하며, 결과는 질의와의 관련도 순으로 정렬된 augment 객체들입니다. 응답 결과에는 호출 가능한 endpoint, protocol, score, definition 등이 들어가므로, caller는 반환된 정보를 바탕으로 실제 agent/tool을 호출할 수 있습니다.

MCP와의 관계

Who 자체도 MCP tool로 노출될 수 있습니다. 공식 MCP binding 문서는 who tool이 “query를 도와줄 agents, tools, services를 찾고, invocation detail을 포함한 ranked augments를 반환한다”고 정의합니다. 즉, LLM agent는 MCP를 통해 먼저 who를 호출해 적절한 도구를 찾고, 이후 반환된 MCP/NLWeb/OpenAPI endpoint를 호출하는 식으로 동작할 수 있습니다.

이 점이 NLWeb discovery의 핵심 가치입니다. 사람이 사이트 검색창에서 검색하는 수준을 넘어, **AI agent가 “이 작업을 할 수 있는 웹 capability를 스스로 찾고 연결”**할 수 있게 합니다.

인덱싱 시 고려사항

Who 서버가 Agent Manifest를 처리할 때는 다음을 해야 한다고 공식 문서는 권장합니다. Manifest schema를 검증하고, skill/tool 설명과 예시 질의를 추출해 검색 가능한 단위로 인덱싱하며, robots.txt 제한을 존중하고, version 필드나 HTTP caching header로 freshness를 추적하고, 가능하면 endpoint availability를 probe합니다. 추가로 query log, success rate, user feedback 같은 신호를 ranking 개선에 활용할 수도 있습니다.

실제로 AgentFinder 구현은 검색 backend와 LLM backend를 분리합니다. README 기준으로 검색 backend는 Azure Search, Elasticsearch, Qdrant 등을 교체 가능하게 두고, LLM backend도 Azure OpenAI, OpenAI, Anthropic 등을 선택할 수 있으며, embedding cache, search cache, ranking cache를 둡니다.

Federation: DNS 같은 계층형 discovery

NLWeb Who는 federation도 고려합니다. 공식 문서는 Who 서버를 DNS처럼 계층화할 수 있다고 설명합니다. 예를 들어 기업 내부에는 internal expense tool, 사내 knowledge base 등을 인덱싱하는 local Who 서버가 있고, 해당 서버가 자체적으로 답하지 못하면 upstream Who 서버나 public/root Who 서버에 위임할 수 있습니다.

이 구조는 신뢰와 정책에도 중요합니다. 기업은 HIPAA, SOC2, GDPR 같은 요건을 만족하는 agent만 노출하거나, 내부 agent를 외부 대안보다 우선시하거나, 특정 agent category를 차단할 수 있습니다. 결과에는 source 필드를 넣어 어느 Who 서버가 해당 결과를 제공했는지 provenance를 표시할 수 있고, 로컬 결과가 부족하면 다른 Who 서버를 가리키는 referrals를 반환할 수도 있습니다.

보안 관점

Discovery는 “찾아준다”는 기능이지 “안전하다고 보증한다”는 기능은 아닙니다. 공식 보안 문서는 caller가 반환된 augment endpoint를 호출하기 전에 신뢰성, 진위, 가용성을 검증해야 하며, custom invocation detail의 inputSchema에 맞게 요청을 검증해야 하고, Who 구현체는 rate limiting을 적용해야 한다고 설명합니다.

실무적으로는 다음을 추가로 보는 것이 좋습니다: endpoint allowlist/denylist, manifest 서명 또는 도메인 소유권 검증, OAuth scope 최소화, tool 호출 전 사용자 확인, prompt-injection 방어, audit log, 결과 ranking에 신뢰도 가중치 반영.

한 줄로 정리

NLWeb discovery는 “AI agent를 위한 검색엔진/전화번호부”에 가깝습니다. 웹사이트나 서비스는 Agent Manifest로 자신의 능력을 광고하고, Who/AgentFinder는 이를 인덱싱해 사용자의 자연어 요청에 가장 적합한 NLWeb agent, MCP tool, A2A agent, OpenAPI, skill을 찾아 호출 정보와 함께 반환합니다. 이 덕분에 agent는 사전에 모든 tool을 하드코딩하지 않고도, 웹 전체에서 필요한 capability를 발견하고 사용할 수 있게 됩니다.

출처