I rebuilt on-demand tool discovery as an independent Python module. Without an account or browser, it demonstrates family discovery, exact-name selection, exclusion of disabled tools and rejection of unknown fields. It deliberately contains no execution engine.

Separate reading definitions from invoking operations

Catalog entries contain only name, family, effect, enabled and fields. A field declares one scalar type, required status and a string-length bound. The full definition is checked before enabled tools in the requested family are returned. Duplicate names or unknown definition fields invalidate the catalog.

The function does not skip corrupt entries while looking for something else executable. Definitions assert which tools exist, so a real adapter must control their provenance. This example supplies neither an external catalog loader nor an installation operation.

All still excludes disabled tools

Discover accepts a family and optional exact name. A reading request does not include another family's input tool. All removes the family filter, not the enabled filter. Naming a disabled tool directly still fails as unavailable.

A similar name or first catalog item is not substituted. An unknown family fails separately. Discovery failure also differs from execution failure: no execution has started here, and the caller needs to inspect the current definition rather than retry an operation.

Use the same small grammar for description and validation

The returned input schema is derived from fields. Argument validation uses that description to check allowed and required keys, scalar types and string lengths. This reduces drift between two separately handwritten contracts.

The grammar is deliberately limited. It does not validate nested objects, dates, URLs or integer sign and magnitude and is not a complete JSON Schema validator. The shared max-length metadata applies only to strings. A real integration must add required semantic and numeric conditions while updating description and validation together.

Explore the implementation

Complete independent synthetic implementation

"""Discover and validate a deliberately small scalar contract. No executor."""
import copy
import re

class CatalogError(ValueError):pass

def _keys(value,fields):
    if not isinstance(value,dict) or set(value)!=set(fields):raise CatalogError('INVALID_FIELDS')

def _label(value):
    if not isinstance(value,str) or not re.fullmatch(r'[a-z][a-z0-9._-]{0,79}',value):raise CatalogError('INVALID_LABEL')

def _catalog(items):
    if not isinstance(items,list) or len(items)>1000:raise CatalogError('INVALID_CATALOG')
    names=set()
    for item in items:
        _keys(item,['name','family','effect','enabled','fields'])
        _label(item['name']);_label(item['family'])
        if item['name'] in names:raise CatalogError('DUPLICATE_TOOL')
        names.add(item['name'])
        if item['effect'] not in ['read','change'] or type(item['enabled']) is not bool:raise CatalogError('INVALID_METADATA')
        if not isinstance(item['fields'],dict) or len(item['fields'])>30:raise CatalogError('INVALID_FIELDS')
        for name,spec in item['fields'].items():
            _label(name);_keys(spec,['type','required','max_length'])
            if spec['type'] not in ['string','integer','boolean'] or type(spec['required']) is not bool:raise CatalogError('INVALID_SPEC')
            if type(spec['max_length']) is not int or not 1<=spec['max_length']<=20000:raise CatalogError('INVALID_SPEC')
    return items

def discover(items,family,name=None):
    _catalog(items);_label(family)
    if name is not None:_label(name)
    families={x['family'] for x in items}
    if family!='all' and family not in families:raise CatalogError('UNKNOWN_FAMILY')
    chosen=[x for x in items if x['enabled'] and (family=='all' or x['family']==family) and (name is None or x['name']==name)]
    if name is not None and not chosen:raise CatalogError('TOOL_NOT_AVAILABLE_IN_FAMILY')
    out=[]
    for item in chosen:
        properties={}
        for key,spec in item['fields'].items():
            properties[key]={'type':spec['type']}
            if spec['type']=='string':properties[key]['maxLength']=spec['max_length']
        out.append({'name':item['name'],'family':item['family'],'effect':item['effect'],'inputSchema':{'type':'object','properties':properties,'required':[k for k,v in item['fields'].items() if v['required']],'additionalProperties':False},'executes':False})
    return copy.deepcopy(out)

def validate_arguments(items,name,arguments):
    """Checks data only. It grants no permission and starts no operation."""
    descriptions=discover(items,'all',name)
    schema=descriptions[0]['inputSchema'];fields=schema['properties']
    if not isinstance(arguments,dict) or set(arguments)-set(fields) or set(schema['required'])-set(arguments):raise CatalogError('INVALID_ARGUMENT_KEYS')
    for key,value in arguments.items():
        spec=fields[key];kind=spec['type']
        if kind=='string':
            if not isinstance(value,str) or len(value)>spec['maxLength']:raise CatalogError('INVALID_ARGUMENT_VALUE')
        elif kind=='integer':
            if type(value) is not int:raise CatalogError('INVALID_ARGUMENT_VALUE')
        elif type(value) is not bool:raise CatalogError('INVALID_ARGUMENT_VALUE')
    return {'name':name,'arguments':copy.deepcopy(arguments),'shape_valid':True,'authorized':False,'executed':False}

Test the distinction between classification and permission

The reading example intentionally includes a state-changing tab selection. A family label is not evidence that every operation is free of side effects. Validation always returns authorization and execution as false. Correct shape grants no right to operate an account or task.

Twenty-one tests cover family exclusion, exact names, disabled and missing tools, corrupt definitions and duplicate names. They reject booleans used as integers and integers used as booleans. Strings at the limit remain intact; oversized strings fail rather than being truncated. Mutating a returned description must not alter the original definition.

Distinguish displayed records from the tested runtime

Five synthetic records show family discovery, one exact tool, valid shape without permission, disabled-tool rejection and unknown-argument rejection. Local Python generated the records; the selector reads them. It does not discover a visitor's actual programs or execute tools.

After twenty-one source-folder tests, the package procedure compares ZIP bytes and entry hashes, extracts into another folder and runs the same tests. Actual inline selector code for both languages is checked with DOM stubs. This does not establish rendered-browser or keyboard verification or a full regression run of Northstar itself.

A read-only viewer of synthetic local records

Responsibilities a real adapter must retain

The ZIP contains the implementation, synthetic definitions, tests, record generator and README. It uses the standard library and permits modification and reuse. The core has no file reads, network calls, account values or execution callback; only the generator writes adjacent synthetic JSON.

A production adapter needs trusted definitions, tool-specific meaning checks, actual account and project permissions, live-state checks and observed outcomes. It also needs to track the discovered contract's version. I share this as a small testable component for selecting precise descriptions, not as a complete automation system.

Download code, tests and records
Python standard library, synthetic data, modification and reuse permitted