Query Skills
# Query Skills
Search and filter capabilities to find the right person or agent for a task.
This pattern shows you how to query the Capability Graph to discover who has specific skills, experience levels, or training certifications.
When to Use This
Architecture
┌─────────────────────────────────────────────────────┐
│ Your Application (Task Assignment) │
└────────────────────┬────────────────────────────────┘
│
▼
┌──────────────────────┐
│ Capability Query │
│ (filter by skill, │
│ level, certification) │
└──────────┬───────────┘
│
▼
┌──────────────────────────────┐
│ Capability Graph Engine │
│ - Indexes capabilities │
│ - Supports filters │
│ - Returns matches │
└──────────┬───────────────────┘
│
▼
┌────────────────────────────────┐
│ Matching Capabilities │
│ - Passport IDs │
│ - Skill levels │
│ - Certifications │
└────────────────────────────────┘Prerequisites
Implementation
Basic Skill Query
Find all entities with a specific skill:
Query by Multiple Criteria
Find entities matching multiple skills (comma-separated or array — same skills field):
import { HumanClient } from '@human/sdk';const client = new HumanClient({
delegationToken: process.env.HUMAN_DELEGATION_TOKEN!,
});
const { data, error } = await client.raw.POST('/v1/capabilities/query', {
body: {
skills: ['contract_review', 'legal_compliance'],
domains__in: ['legal'],
min_weight: 0.7,
limit: 5,
},
});
if (error) throw error;
const matches = Array.isArray(data?.data) ? data.data : [];
console.log(Top matches: ${matches.length});
for (const row of matches) {
console.log(- ${row.passport_did}: ${row.capability?.canonical_name ?? row.capability_id});
}
curl -s -X POST https://api.haio.run/v1/capabilities/query \
-H "Authorization: Bearer $HUMAN_DELEGATION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"skills":["contract_review","legal_compliance"],"domains__in":["legal"],"min_weight":0.7,"limit":5}'Query with Sort and Pagination
const { data, error } = await client.raw.POST('/v1/capabilities/query', {
body: {
skills: ['invoice_processing'],
sort: '-weight,granted_at',
limit: 50,
cursor: process.env.NEXT_CURSOR, // opaque cursor from prior next_cursor
},
});
if (error) throw error;console.log(page size=${data?.data?.length ?? 0} has_more=${data?.has_more});
curl -s -X POST https://api.haio.run/v1/capabilities/query \
-H "Authorization: Bearer $HUMAN_DELEGATION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"skills":["invoice_processing"],"sort":"-weight,granted_at","limit":50}'Use Cases
Task Assignment
Query to find the best person or agent for a specific task based on required skills and availability
Talent Discovery
Discover internal talent with specific skill combinations for projects or initiatives
Training Gaps
Identify skill gaps across the organization to inform training programs
Team Building
Find complementary skills to build balanced project teams
Best Practices
Performance
Accuracy
Privacy
Security Considerations
DO
Verify the querying entity has permission to view results
Log all capability queries for audit trails
Filter results based on the requester's access level
Validate skill names against the canonical ontology
DON'T
Return capabilities marked as private without explicit consent
Allow unauthenticated queries
Expose personally identifiable information in query results
Cache capability data without considering staleness
Common Patterns
Pattern: Skill-Based Routing
async function routeTask(
client: HumanClient,
requiredSkills: string[],
minWeight = 0.7,
): Promise {
const { data, error } = await client.raw.POST('/v1/capabilities/query', {
body: { skills: requiredSkills, min_weight: minWeight, limit: 10 },
});
if (error) throw error; const matches = Array.isArray(data?.data) ? data.data : [];
if (matches.length === 0) {
throw new Error('No qualified candidates found');
}
const best = matches[0];
return best.passport_did as string;
}
Pattern: Skill Coverage Check
async function analyzeSkillCoverage(
client: HumanClient,
targetSkills: string[],
) {
const { data, error } = await client.raw.POST('/v1/capabilities/query', {
body: { skills: targetSkills, limit: 100 },
});
if (error) throw error; const rows = Array.isArray(data?.data) ? data.data : [];
const found = new Set(
rows.map((r) => r.capability?.canonical_name ?? r.capability_id).filter(Boolean),
);
const gaps = targetSkills.filter((skill) => !found.has(skill));
return { found: [...found], gaps };
}
Query by domain (alias)
/docs/patterns/capability-graph/query-capabilities-by-domain is an alias. Filter with domain (or ontology path) on the same query surface:
const { data, error } = await client.raw.POST('/v1/capabilities/query', {
body: {
domain: 'finance',
skills: ['invoice_processing'],
limit: 20,
},
});
if (error) throw error;