Skip to content

Conversation

@zomux
Copy link
Contributor

@zomux zomux commented Feb 3, 2026

No description provided.

Copilot AI review requested due to automatic review settings February 3, 2026 08:21
@vercel
Copy link

vercel bot commented Feb 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openagents-studio Ready Ready Preview, Comment Feb 3, 2026 8:38am

Request Review

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an AgentID verification/authentication module and wires it into the CLI, along with comprehensive unit tests.

Changes:

  • Add AgentID parsing, models, exceptions, and an HTTP client (AgentIDVerifier / AgentIDAuth) with async and sync APIs.
  • Add CLI command group agentid with subcommands for parsing IDs, verifying agents, resolving DIDs, handling challenges, and obtaining/validating JWT tokens.
  • Add focused tests for the AgentID parser, client, and authentication flow.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/openagents/agentid/parser.py Implements validation, parsing, normalization, and format detection for AgentID strings (simple, level_2, level_3).
src/openagents/agentid/models.py Defines Pydantic models for parsed IDs, verification results, registry info, token/challenge responses, and DID documents.
src/openagents/agentid/exceptions.py Adds a structured hierarchy of AgentID-specific exceptions for format, not-found, connection, and auth errors.
src/openagents/agentid/client.py Provides async and sync clients for registry lookups, DID resolution, token verification, challenge issuance, and JWT acquisition, plus the AgentIDAuth helper.
src/openagents/agentid/__init__.py Exposes the AgentID public API (clients, models, parser helpers, and exceptions) for convenient imports.
src/openagents/cli.py Registers a new agentid Typer command group with parse/verify/info/resolve/verify-token/challenge/token/auth commands wired to the new client APIs.
tests/agentid/test_parser.py Adds tests covering name/org validation, parsing across all formats, normalization helpers, and format detection.
tests/agentid/test_client.py Adds tests for async client behavior (success and error paths) and the AgentIDAuth signing-and-token flow.
tests/agentid/__init__.py Marks the tests.agentid package for the new test suite.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 422 to 436
"""Run an async coroutine synchronously."""
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None

if loop and loop.is_running():
# We're in an async context, can't use run_until_complete
import concurrent.futures

with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(asyncio.run, coro)
return future.result()
else:
return asyncio.run(coro)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_run_async can reuse the same aiohttp.ClientSession across different event loops when called from an already-running event loop, because self._session is cached and not tied to a specific loop. This will break scenarios where sync methods like validate() are called multiple times from async code (each call spawns a new event loop in a background thread but may reuse the existing session created in a previous loop), which is unsupported in aiohttp and can raise runtime errors. Consider either (1) disallowing sync methods when an event loop is already running (e.g., by raising a clear error), or (2) moving all sync usage to a dedicated long-lived event loop/thread and ensuring the session is created and used only within that loop, instead of caching a session that may outlive its loop.

Suggested change
"""Run an async coroutine synchronously."""
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None
if loop and loop.is_running():
# We're in an async context, can't use run_until_complete
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(asyncio.run, coro)
return future.result()
else:
return asyncio.run(coro)
"""Run an async coroutine synchronously.
Note:
This helper is intended for use from synchronous code only.
If an event loop is already running (i.e., we're in async code),
callers must use the corresponding async methods directly
(e.g., ``validate_async``, ``get_agent_info_async``).
"""
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = None
if loop and loop.is_running():
# We're in an async context; to avoid reusing resources like
# aiohttp.ClientSession across different event loops (which is
# unsupported), require callers to use the async APIs directly.
raise RuntimeError(
"Synchronous AgentID client methods cannot be called from an "
"asyncio event loop. Use the corresponding '*_async' methods."
)
return asyncio.run(coro)

Copilot uses AI. Check for mistakes.
authentication, and DID document handling.
"""

from typing import Optional, List, Dict, Any, Literal
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Literal is imported but never used in this module, which adds minor noise and may trigger linting warnings. Please remove the unused import or use it where intended to keep the models file clean.

Suggested change
from typing import Optional, List, Dict, Any, Literal
from typing import Optional, List, Dict, Any

Copilot uses AI. Check for mistakes.
import base64
import logging
from pathlib import Path
from typing import Optional, Union
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'Optional' is not used.

Suggested change
from typing import Optional, Union
from typing import Union

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +37
AgentIDError,
AgentIDNotFoundError,
AgentIDConnectionError,
AgentIDAuthenticationError,
AgentIDSignatureError,
AgentIDChallengeExpiredError,
AgentIDTokenExpiredError,
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'AgentIDError' is not used.
Import of 'AgentIDAuthenticationError' is not used.
Import of 'AgentIDTokenExpiredError' is not used.

Suggested change
AgentIDError,
AgentIDNotFoundError,
AgentIDConnectionError,
AgentIDAuthenticationError,
AgentIDSignatureError,
AgentIDChallengeExpiredError,
AgentIDTokenExpiredError,
AgentIDNotFoundError,
AgentIDConnectionError,
AgentIDSignatureError,
AgentIDChallengeExpiredError,

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +15
from openagents.agentid.models import (
VerificationResult,
AgentInfo,
ChallengeResponse,
TokenResponse,
DIDDocument,
TokenValidationResult,
AgentIDLevel,
)
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'VerificationResult' is not used.

Copilot uses AI. Check for mistakes.
)
from openagents.agentid.exceptions import (
AgentIDNotFoundError,
AgentIDConnectionError,
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'AgentIDConnectionError' is not used.

Suggested change
AgentIDConnectionError,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants