Skip to main content

Why this API is agent-friendly

Traditional building APIs require opaque UUIDs for every lookup. An AI agent can’t ask “what VAVs are in the Library?” without first discovering the Library’s UUID, then querying equipment by location ID. Tacit’s API eliminates this friction. An agent can:
  1. Discover by name: equipment(name: "AHU") finds equipment without UUIDs
  2. Query across the graph: points(locationName: "Tower East", equipmentIs: "VAV", is: "Temperature_Sensor") joins locations, equipment, and points in one request
  3. Reason with class hierarchy: is: "HVAC_Equipment" matches all subtypes without knowing the taxonomy
  4. Trace relationships: upstream and downstream follow equipment chains to find root causes

Multi-tenant scoping

Every root query requires a siteId parameter. Your agent should store this as configuration, as it scopes all queries to a specific site’s knowledge graph. See multi-tenant scoping.
Examples below omit siteId for brevity. In practice, every root query includes it.

Agent query patterns

Pattern 1: Discovery - “What’s in this building?”

An agent starts by understanding the building’s structure:
{
  buildings { id name type }
}
Then explores the spatial hierarchy:
{
  building(id: "B001") {
    name
    locations {
      name
      type
      locations { name type }
    }
  }
}

Pattern 2: Cross-cutting search - “Find specific sensors”

The most powerful pattern for agents. Instead of chaining multiple queries with UUIDs, ask a single cross-cutting question:
# "What are the supply air temperatures on AHUs in Tower West?"
{
  point(locationName: "Tower West", equipmentIs: "AHU", is: "Supply_Air_Temperature_Sensor") {
    name
    type
    unit
    equipment { name }
  }
}
# "Show me all temperature sensors on VAVs"
{
  point(equipmentIs: "VAV", is: "Temperature_Sensor") {
    name
    type
    unit
    equipment { name type }
    location { name }
  }
}

Pattern 3: Topology - “What feeds what?”

Trace the equipment chain to understand dependencies:
# "What does AHU-001 feed?"
{
  equipment(id: "TE01-XX-AHU-001") {
    name
    feeds {
      name
      type
      points(is: "Zone_Air_Temperature_Sensor") {
        name
        unit
      }
    }
  }
}
# "Where does this AHU get hot water from?"
{
  equipment(id: "TE01-XX-AHU-001") {
    name
    upstream(medium: "HOT_WATER") {
      name
      type
    }
  }
}

Pattern 4: Diagnostics - “What’s the blast radius?”

Combine traversal with point queries for root cause analysis:
# "If AHU-001 fails, what zones are affected and what are their sensors?"
{
  equipment(id: "TE01-XX-AHU-001") {
    name
    points(is: "Temperature_Sensor") {
      name type unit
    }
    downstream(maxDepth: 5) {
      name
      type
      points(is: "Temperature_Sensor") {
        name type unit
      }
    }
  }
}

Pattern 5: Property filtering - “Find by metadata”

# "What equipment is on this BACnet controller?"
{
  equipment(hasProperty: "controllerName", propertyValue: "PSW TE01-XX-MCC-001") {
    name
    type
    location { name }
  }
}

Architecture

AI Agent (Claude / GPT / custom)

    ├── discover()  ──▶ Tacit GraphQL ──▶ buildings, equipment by name
    ├── observe()   ──▶ Tacit GraphQL ──▶ points, cross-cutting queries
    ├── diagnose()  ──▶ Tacit GraphQL ──▶ upstream/downstream traversal
    └── history()   ──▶ Tacit REST    ──▶ timeseries data for analysis

MCP server integration

The fastest path for Claude-based agents is connecting via MCP (Model Context Protocol). This gives Claude direct access to Tacit’s GraphQL API as a tool. See MCP server setup for configuration.

Key advantages for AI agents

Traditional APITacit GraphQL
Need UUID to query anythingSearch by name: equipment(name: "AHU")
Multiple round-trips to join dataOne cross-cutting query: points(locationName: "...", equipmentIs: "...", is: "...")
Must know exact equipment typesSemantic resolution: is: "HVAC_Equipment" matches all subtypes
Manual recursive calls for chainsBuilt-in traversal: upstream, downstream
Flat JSON blobs for propertiesStructured: properties { name value unit } with hasProperty filtering