{
  "schemaVersion": "a2a/v1",
  "name": "EventFinder",
  "description": "Live music and event listings (currently San Francisco), machine-readable.",
  "version": "20260518-161637",
  "generated_at": "2026-05-18T16:16:37Z",
  "url": "https://ef.bulkowski.org",
  "provider": {
    "name": "EventFinder",
    "contact": "brian@bulkowski.org"
  },
  "cities": [
    {
      "slug": "san_francisco_metro",
      "name": "San Francisco Metro",
      "timezone": "America/Los_Angeles"
    }
  ],
  "endpoints": {
    "data": {
      "schema": "https://ef.bulkowski.org/data/v1/README.md",
      "manifest": "https://ef.bulkowski.org/data/v1/manifest.json",
      "version": "https://ef.bulkowski.org/data/v1/version.json",
      "bundle": "https://ef.bulkowski.org/data/v1/bundle.json",
      "tarball": "https://ef.bulkowski.org/data/v1/bundle.tar.gz",
      "perCity": "https://ef.bulkowski.org/data/v1/cities/{city}/bundle.json",
      "today": "https://ef.bulkowski.org/data/v1/cities/{city}/events/today.json",
      "next7": "https://ef.bulkowski.org/data/v1/cities/{city}/events/next_7.json",
      "perDate": "https://ef.bulkowski.org/data/v1/cities/{city}/events/{YYYY-MM-DD}.json",
      "eventTypes": "https://ef.bulkowski.org/data/v1/event_types.json",
      "cities": "https://ef.bulkowski.org/data/v1/cities.json"
    },
    "discovery": {
      "llmsTxt": "https://ef.bulkowski.org/llms.txt",
      "robotsTxt": "https://ef.bulkowski.org/robots.txt",
      "sitemap": "https://ef.bulkowski.org/sitemap.xml",
      "alternateLink": "https://ef.bulkowski.org/data/v1/manifest.json"
    },
    "search": {
      "events": "https://ef.bulkowski.org/api/v1/events/search"
    }
  },
  "skills": [
    {
      "id": "search_events",
      "name": "Search events",
      "description": "Find events matching a date range, region, neighborhood, venue, event type, or free-text query. Use this for any narrow user question (\"jazz events Saturday\", \"classical music in Oakland next week\") — it returns only matching events without the agent having to download daily files or join venues→geo.json themselves. All parameters are optional; default date range is today + 7 days in the city's local timezone.",
      "tags": [
        "search",
        "events",
        "filter",
        "query"
      ],
      "method": "GET",
      "endpoint": "https://ef.bulkowski.org/api/v1/events/search",
      "inputSchema": {
        "type": "object",
        "properties": {
          "city": {
            "type": "string",
            "description": "City slug. Optional if only one city is configured. Slugs in cities.json.",
            "example": "san_francisco_metro"
          },
          "event_type": {
            "type": "string",
            "description": "Event type id. Values from https://ef.bulkowski.org/data/v1/event_types.json.",
            "examples": [
              "live_music",
              "jazz",
              "classical",
              "trivia"
            ]
          },
          "region": {
            "type": "string",
            "description": "Region name. Values from https://ef.bulkowski.org/data/v1/cities/{city}/geo.json `regions` keys.",
            "examples": [
              "San Francisco",
              "East Bay",
              "Oakland"
            ]
          },
          "neighborhood": {
            "type": "string",
            "description": "Single neighborhood name (e.g. 'Mission', 'Berkeley')."
          },
          "venue": {
            "type": "string",
            "description": "Exact venue name match."
          },
          "date_from": {
            "type": "string",
            "format": "date",
            "description": "Inclusive lower bound, YYYY-MM-DD. Default: today in city tz."
          },
          "date_to": {
            "type": "string",
            "format": "date",
            "description": "Inclusive upper bound, YYYY-MM-DD. Default: date_from + 7 days."
          },
          "q": {
            "type": "string",
            "description": "Substring match against title, venue_name, and description (diacritics-insensitive)."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "default": 200,
            "description": "Max events returned. `truncated: true` in the response indicates more matches exist."
          }
        },
        "required": []
      },
      "outputSchema": {
        "type": "object",
        "description": "JSON object with `events` array, plus echoed `filters`, `count`, `total_matches`, `limit`, `truncated`, and `date_from`/`date_to` defaults. Event objects use the same schema as per-date files; field reference at https://ef.bulkowski.org/data/v1/README.md."
      },
      "examples": [
        {
          "name": "Tonight's jazz",
          "url": "https://ef.bulkowski.org/api/v1/events/search?event_type=jazz"
        },
        {
          "name": "Classical in Oakland next week",
          "url": "https://ef.bulkowski.org/api/v1/events/search?event_type=classical&region=Oakland"
        },
        {
          "name": "All events on a specific date",
          "url": "https://ef.bulkowski.org/api/v1/events/search?date_from=2026-05-15&date_to=2026-05-15"
        },
        {
          "name": "Free-text search across the next 30 days",
          "url": "https://ef.bulkowski.org/api/v1/events/search?q=cello&date_to=2026-06-09"
        }
      ],
      "inputModes": [
        "application/x-www-form-urlencoded"
      ],
      "outputModes": [
        "application/json"
      ]
    }
  ],
  "entry_point": "https://ef.bulkowski.org/data/v1/manifest.json",
  "consumption_guidance": {
    "start_here": "Begin with the manifest at https://ef.bulkowski.org/data/v1/manifest.json (a few KB). It carries the full `endpoints` map (data files), a `discovery` block (llms.txt, agent-card.json, README), per-file sha256 + sizes, and the bundle's content-hash. The `X-Agent-Data` response header on every endpoint also points here. Do NOT use bundle.json as a first fetch — it is multi-MB and will overflow most LLM context windows.",
    "narrow_queries": "Prefer per-date endpoints (~5K tokens each) and today.json / next_7.json. These fit in any model's context.",
    "batch_consumers": "Use bundle.json (~6-7 MB raw, ~1.5-2M tokens) only if you are indexing offline or have a model with sufficient context. For LLM-context-bounded agents, bundle.json will overflow Sonnet, Haiku, and most frontier model context windows.",
    "cache_validation": "GET https://ef.bulkowski.org/data/v1/version.json (~100 bytes) to check if your cached copy is still current; the sha256 there matches the ETag of bundle.json.",
    "by_endpoint": {
      "today": {
        "url": "https://ef.bulkowski.org/data/v1/cities/{city}/events/today.json",
        "size_hint": "~5-50 KB",
        "use_for": "Single-day query: \"events tonight\", \"what's on today\". Auto-resolves to today's date in the city's local timezone."
      },
      "per_date": {
        "url": "https://ef.bulkowski.org/data/v1/cities/{city}/events/{YYYY-MM-DD}.json",
        "size_hint": "~5-50 KB",
        "use_for": "Single-day query for a specific date. Use events/index.json to discover available dates."
      },
      "next_7": {
        "url": "https://ef.bulkowski.org/data/v1/cities/{city}/events/next_7.json",
        "size_hint": "~50-200 KB",
        "use_for": "Week-ahead planning. Auto-resolves the start date in the city's local timezone."
      },
      "city_bundle": {
        "url": "https://ef.bulkowski.org/data/v1/cities/{city}/bundle.json",
        "size_hint": "~500 KB - 2 MB",
        "use_for": "Full snapshot of one city (all dates, venues, geo). Fits a Sonnet 4 context window."
      },
      "master_bundle": {
        "url": "https://ef.bulkowski.org/bundle.json",
        "size_hint": "~7 MB / ~2M tokens",
        "use_for": "Batch indexing only. Will OVERFLOW Sonnet, Haiku, and most frontier-model context windows. Do NOT load into an LLM context for narrow queries — it WILL truncate."
      }
    },
    "filter_by_neighborhood_or_region": "**Prefer the search endpoint** at /api/v1/events/search?region=... or ?neighborhood=... — it does the join for you and returns only matching events. Manual fallback (for batch consumers reading the static date files): event records carry venue_id but not neighborhood or region. To filter manually: (1) GET cities/{city}/venues.json once; (2) build a lookup keyed by venue.id; (3) for each event, strip the 'venue_' prefix from event.venue_id and look up the venue; (4) read venue.neighborhood. For region-level filtering, also GET cities/{city}/geo.json — its 'regions' map names → list of neighborhoods, so a venue's region is the region whose neighborhood list contains venue.neighborhood. Note: there is NO 'region' field on venue records; region is derived via geo.json."
  },
  "license": "https://ef.bulkowski.org/LICENSE"
}