Skip to content

get_properties_by_agent() doesn't support property_tags/property_ids authorization types #99

@bokelley

Description

@bokelley

Summary

The get_properties_by_agent() function in adcp/adagents.py only returns properties when an agent uses inline properties authorization. It doesn't work for agents authorized via:

  • property_tags - filtering top-level properties by tags
  • property_ids - filtering top-level properties by IDs
  • publisher_properties - complex domain-based selection

Additionally, AuthorizationContext uses prop.get("id") but AdCP v2 schema uses property_id.

Steps to Reproduce

Given an adagents.json like wasmer.ca's:

{
  "authorized_agents": [
    {
      "url": "https://adcp.wasmer.ca",
      "authorization_type": "property_tags",
      "property_tags": ["adcp-triton"]
    }
  ],
  "properties": [
    {
      "property_id": "696023",
      "property_type": "podcast",
      "name": "Example Podcast",
      "tags": ["adcp-triton"]
    }
    // ... 2944 more properties
  ]
}

Calling:

from adcp.adagents import fetch_adagents, get_properties_by_agent, AuthorizationContext

adagents_data = await fetch_adagents("wasmer.ca")
properties = get_properties_by_agent(adagents_data, "https://adcp.wasmer.ca")
ctx = AuthorizationContext(properties)

print(len(properties))  # 0 - WRONG! Should be 2944
print(ctx.property_ids)  # [] - WRONG!

Expected Behavior

get_properties_by_agent() should:

  1. Detect the authorization type (inline_properties, property_tags, property_ids, publisher_properties)
  2. For property_tags: Filter top-level properties array by matching tags
  3. For property_ids: Filter top-level properties array by matching IDs
  4. For unrestricted agents (no auth fields): Return all top-level properties

Current Behavior

The function only looks for agent.get("properties", []) at line 514:

# Found the agent - return their properties
properties = agent.get("properties", [])  # Only handles inline properties!

Root Cause

Two issues in adcp/adagents.py:

1. get_properties_by_agent() (lines 478-520)

Only handles inline properties authorization:

properties = agent.get("properties", [])

Needs to handle:

  • authorization_type: "property_tags" with agent.property_tags
  • authorization_type: "property_ids" with agent.property_ids
  • authorization_type: "publisher_properties" with agent.publisher_properties

2. AuthorizationContext.__init__() (lines 542-557)

Uses wrong key:

prop_id = prop.get("id")  # Should be "property_id" per AdCP v2 schema

Proposed Fix

Here's a working implementation we're using as a workaround:

def get_properties_by_agent_enhanced(
    adagents_data: dict[str, Any],
    agent_url: str,
) -> list[dict[str, Any]]:
    """Get all properties authorized for a specific agent.
    
    Handles all authorization types:
    - inline_properties: Properties in agent.properties array
    - property_ids: Filter top-level properties by property_id
    - property_tags: Filter top-level properties by tags
    - publisher_properties: Complex domain-based selection
    """
    # ... validation ...
    
    top_level_properties = adagents_data.get("properties", [])
    
    for agent in authorized_agents:
        if normalize_url(agent.get("url", "")) != normalized_agent_url:
            continue
            
        # Check which authorization fields are present
        has_inline_properties = "properties" in agent and agent.get("properties")
        has_property_ids = "property_ids" in agent and agent.get("property_ids")
        has_property_tags = "property_tags" in agent and agent.get("property_tags")
        has_publisher_properties = "publisher_properties" in agent and agent.get("publisher_properties")
        
        # Unrestricted agent = access to ALL properties
        if not (has_inline_properties or has_property_ids or has_property_tags or has_publisher_properties):
            return list(top_level_properties)
        
        if has_inline_properties:
            return agent.get("properties", [])
        
        elif has_property_tags:
            authorized_tags = set(agent.get("property_tags", []))
            return [p for p in top_level_properties 
                    if set(p.get("tags", [])) & authorized_tags]
        
        elif has_property_ids:
            authorized_ids = set(agent.get("property_ids", []))
            return [p for p in top_level_properties 
                    if p.get("property_id") in authorized_ids]
        
        # ... handle publisher_properties ...
    
    return []

Environment

  • adcp version: 2.13.0
  • Python: 3.12
  • Real-world publisher affected: wasmer.ca (2944 podcast properties)

Workaround

We've implemented enhanced versions in our sales agent codebase that properly handle all authorization types. Happy to contribute a PR if helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions