selectArtefacts
selectArtefacts(by: ...) is the slim, repo-scoped DevQL GraphQL selector for agent-oriented code analysis.
It lets you:
- select a current set of artefacts once
- ask for one aggregate
overviewacross all supported categories - drill into one category only when that overview suggests it is worth the tokens
This is the intended shape for tool-using agents.
Availability
selectArtefacts(by: ...) is available on the slim GraphQL surface only.
- Raw GraphQL: supported
- Slim
/devqlSDL and Explorer: supported - DevQL DSL compiler: supported for one explicit terminal stage at a time
- DevQL DSL aggregate
selectArtefacts(...)->overview(): not supported yet - Global/full GraphQL surface: not supported
Selector Modes
Exactly one selector mode must be used.
By symbolFqn
{
selectArtefacts(by: { symbolFqn: "rust-app/src/main.rs::main" }) {
count
artefacts {
path
symbolFqn
summary
embeddingRepresentations
}
}
}
This usually resolves to 0..1 logical artefacts, but callers should treat the result as a set.
By search
{
selectArtefacts(by: { search: "payLater()" }) {
count
artefacts {
path
symbolFqn
summary
embeddingRepresentations
}
}
}
search runs two internal lanes and returns one flat artefact list:
- up to 5 fuzzy symbol-name matches, including typo-tolerant requests such as
payLater()orpayLatr() - up to 5 embedding-backed conceptual matches across identity, code, and summary representations
Fuzzy hits are returned first, embedding-only hits follow, weak matches are dropped, and score remains optional debug output rather than part of the default contract.
By path and lines
{
selectArtefacts(by: { path: "rust-app/src/main.rs", lines: { start: 6, end: 10 } }) {
count
artefacts {
path
symbolFqn
summary
embeddingRepresentations
startLine
endLine
}
}
}
This resolves all current artefacts in that file whose ranges overlap the selected line span.
By path
{
selectArtefacts(by: { path: "rust-app/src/main.rs" }) {
count
artefacts {
path
symbolFqn
summary
embeddingRepresentations
}
}
}
This resolves all current artefacts in the file.
Validation Rules
symbolFqncannot be combined withsearch,path, orlinessearchcannot be combined withsymbolFqn,path, orlinessearchmust be non-emptylinesrequirespath- empty selectors are rejected
- selector paths are resolved relative to the slim request scope, including project-scoped slim requests
- selection is current-state only in v1;
asOf(...)is not part of this surface
Selection Shape
selectArtefacts(by: ...) returns one ArtefactSelection object representing the selected set.
type ArtefactSelection {
count: Int!
overview: JSON!
artefacts(first: Int! = 20): [Artefact!]!
checkpoints(agent: String, since: DateTime): CheckpointStageResult!
dependencies(kind: EdgeKind, direction: DepsDirection! = BOTH, includeUnresolved: Boolean! = true): DependencyStageResult!
codeMatches(relationKind: String, minScore: Float): CloneStageResult!
tests(minConfidence: Float, linkageSource: String): TestsStageResult!
historicalContext(agent: String, since: DateTime, evidenceKind: HistoricalEvidenceKind): HistoricalContextStageResult!
contextGuidance(agent: String, since: DateTime, evidenceKind: HistoricalEvidenceKind, category: ContextGuidanceCategory, kind: String): ContextGuidanceStageResult!
}
Use:
countto know how many artefacts matchedartefacts(...)when you want to inspect the matched set itself- each returned
Artefactcan expose semanticsummaryplusembeddingRepresentations overviewwhen you want one compact answer across all supported categories- stage fields when you want one category in more detail
Aggregate overview
The selection-level overview field returns a JSON object with one entry per supported category.
{
selectArtefacts(by: { path: "rust-app/src/main.rs", lines: { start: 6, end: 10 } }) {
overview
}
}
Representative shape:
{
"selectedArtefactCount": 2,
"checkpoints": {
"overview": {
"totalCount": 0,
"latestAt": null,
"agents": []
},
"schema": null
},
"codeMatches": {
"overview": {
"counts": {
"total": 2,
"similar_implementation": 2
},
"expandHint": {
"intent": "Inspect code matches",
"template": "bitloops devql query '{ selectArtefacts(by: ...) { codeMatches(relationKind: <KIND>) { items(first: 20) { ... } } } }'",
"parameters": [
{
"name": "kind",
"intent": "Choose which relation kind to inspect",
"supportedValues": [
"exact_duplicate",
"similar_implementation",
"shared_logic_candidate",
"diverged_implementation",
"weak_clone_candidate"
]
}
]
}
},
"expandHint": {
"intent": "Inspect code matches",
"template": "bitloops devql query '{ selectArtefacts(by: ...) { codeMatches(relationKind: <KIND>) { items(first: 20) { ... } } } }'",
"parameters": [
{
"name": "kind",
"intent": "Choose which relation kind to inspect",
"supportedValues": [
"exact_duplicate",
"similar_implementation",
"shared_logic_candidate",
"diverged_implementation",
"weak_clone_candidate"
]
}
]
},
"schema": "type ArtefactSelection { ... }"
},
"dependencies": {
"overview": {
"dependencies": {
"selectedArtefact": 2,
"total": 2,
"incoming": 0,
"outgoing": 2,
"kindCounts": {
"calls": 2,
"exports": 0,
"extends": 0,
"implements": 0,
"imports": 0,
"references": 0
}
}
},
"expandHint": {
"intent": "Use direction to filter dependencies by flow relative to the selected artefacts: incoming maps to IN and outgoing maps to OUT. Use kind to filter dependencies by relationship type: kindCounts.calls maps to CALLS, kindCounts.imports maps to IMPORTS and so on.",
"template": "Direction example: bitloops devql query '{ selectArtefacts(...) { dependencies(direction: IN) { items(first: 50) { edgeKind fromArtefact { symbolFqn path startLine endLine } toArtefact { symbolFqn path startLine endLine } toSymbolRef } } } }'",
"parameters": [
{
"name": "direction",
"intent": "Choose dependency flow relative to the selected artefacts",
"supportedValues": ["IN", "OUT"]
},
{
"name": "kind",
"intent": "Choose dependency relationship type",
"supportedValues": ["CALLS", "EXPORTS", "EXTENDS", "IMPLEMENTS", "IMPORTS", "REFERENCES"]
}
]
},
"schema": "type ArtefactSelection { ... }"
},
"tests": {
"overview": {
"selectedArtefactCount": 2,
"matchedArtefactCount": 2,
"totalCoveringTests": 2,
"expandHint": {
"intent": "Inspect concrete covering tests for selected artefacts",
"template": "bitloops devql query '{ selectArtefacts(by: { symbolFqn: \"<symbol-fqn>\" }) { tests { overview items(first: 20) { coveringTests { testName suiteName filePath startLine endLine } } } } }'"
}
},
"schema": "type ArtefactSelection { ... }"
},
"historicalContext": {
"overview": {
"totalCount": 1,
"checkpointCount": 1,
"sessionCount": 1,
"turnCount": 1,
"evidenceCounts": {
"symbolProvenance": 1,
"fileRelation": 1,
"lineOverlap": 0
}
},
"schema": "type ArtefactSelection { ... }"
},
"contextGuidance": {
"overview": {
"totalCount": 1,
"categoryCounts": {
"DECISION": 1
},
"kindCounts": {
"architectural_boundary": 1
}
},
"schema": "type ArtefactSelection { ... }"
}
}
Notes:
overviewis stage-owned JSON, not stringified JSONschemaisnullwhen that stage has no resultsschemais included in the aggregate response so an agent can discover the drill-down surface without re-querying firsttests.overview.expandHintis always included when tests overview is requested and points to the concretecoveringTestsdrill-down queryoverview.dependencies.expandHintmaps the dependency buckets back to concretedependencies(direction:..., kind:...)follow-up queriesoverview.dependencies.expandHintis omitted when no dependencies match the selected artefactscodeMatchesoverviews always includecounts.totalexpandHintis omitted whencounts.totalis0
Stage Results
Each category field returns a typed stage result object.
type CheckpointStageResult {
overview: JSON!
schema: String
items(first: Int! = 20): [Checkpoint!]!
}
The other stage result types follow the same pattern:
CloneStageResultDependencyStageResultTestsStageResultHistoricalContextStageResultContextGuidanceStageResult
CloneStageResult and DependencyStageResult both expose a typed expandHint field:
type CloneStageResult {
overview: JSON!
expandHint: CloneExpandHint
schema: String
items(first: Int! = 20): [Clone!]!
}
type DependencyStageResult {
overview: JSON!
expandHint: DependencyExpandHint
schema: String
items(first: Int! = 20): [DependencyEdge!]!
}
Use them like this:
{
selectArtefacts(by: { path: "rust-app/src/main.rs" }) {
codeMatches {
overview
expandHint {
intent
template
parameters {
name
intent
supportedValues
}
}
items(first: 10) {
relationKind
score
}
}
dependencies {
overview
expandHint {
intent
template
parameters {
name
intent
supportedValues
}
}
schema
items(first: 10) {
id
edgeKind
toSymbolRef
}
}
}
}
This is the normal escalation path:
- Ask for
overview - Decide which category matters
- For
dependencies, use the typed stage fieldexpandHint, or the aggregateoverview.dependencies.expandHintwhen you are still in overview-only mode - Read
schemaonly if needed - Query
items(first: ...)for typed detail rows
Agent Hook Guidance
Bitloops now treats the DevQL hook as guidance-gated. When the Bitloops-managed using-devql guidance surface is enabled for an agent, Bitloops installs the repo-local DevQL guidance surface and emits direct startup guidance for that surface. When that guidance is disabled, Bitloops emits no DevQL guidance at all.
The current enforcement contract is:
- Claude Code and Codex regain targeted prompt-time reinforcement in addition to the repo-local surface
- Cursor remains session-start plus rule-based
- other supported agents follow the same repo-local surface contract when their DevQL Guidance is enabled
The guidance follows the same workflow documented here:
- Start with
selectArtefacts(by: ...) { overview } - Read stage
schemaonly when the overview says a drill-down is worth it - Query
items(first: ...)on the relevant stage for typed rows - Use
bitloops devql schemaorbitloops devql schema --globalwhen the full SDL is needed
This guidance is guidance only. It does not execute DevQL automatically or attach live query results to the turn.
Category Overviews
Current category coverage:
| Category | Overview intent | Detail type |
|---|---|---|
checkpoints | Count, latest timestamp, participating agents | Checkpoint |
codeMatches | Total count, grouped relation kinds, max score | Clone |
tests | Matched artefact count, total covering tests, drill-down hint | TestHarnessTestsResult |
dependencies | Nested counts plus a default drill-down hint for direction / kind follow-up queries | DependencyEdge |
historicalContext | Prior checkpoints, sessions, turns, prompts, transcript previews, tool events, and file relations tied to the selected artefacts | HistoricalContextItem |
contextGuidance | Distilled future-session guidance, grouped by durable categories such as decisions, constraints, risks, and verification requirements | ContextGuidanceItem |
Stage Arguments
checkpoints
checkpoints(agent: String, since: DateTime)
codeMatches
codeMatches(relationKind: String, minScore: Float)
dependencies
dependencies(kind: EdgeKind, direction: DepsDirection! = BOTH, includeUnresolved: Boolean! = false)
Defaults for selection stages:
direction = BOTHincludeUnresolved = false
tests
tests(minConfidence: Float, linkageSource: String)
historicalContext
historicalContext(agent: String, since: DateTime, evidenceKind: HistoricalEvidenceKind)
contextGuidance
contextGuidance(agent: String, since: DateTime, evidenceKind: HistoricalEvidenceKind, category: ContextGuidanceCategory, kind: String)
Use contextGuidance when prior history or linked knowledge has been distilled into durable guidance for the selected artefact. A typical architectural-decision use case is making a past file-level decision visible before a future edit:
{
selectArtefacts(by: { path: "src/target.ts" }) {
contextGuidance(category: DECISION, kind: "architectural_boundary") {
overview
items(first: 5) {
category
kind
guidance
evidenceExcerpt
sources {
checkpointId
turnId
}
}
}
}
}
That lets an agent see guidance such as “keep this file as the boundary for target result calculation” before making the next code change.
DevQL DSL Form
The DevQL DSL supports selectArtefacts(...) with flat selector args:
selectArtefacts(symbol_fqn:"rust-app/src/main.rs::main")->checkpoints()
selectArtefacts(search:"payLater()")->checkpoints()
selectArtefacts(path:"rust-app/src/main.rs",lines:6..10)->deps()
selectArtefacts(path:"rust-app/src/main.rs")->tests(min_confidence:0.8)
selectArtefacts(path:"rust-app/src/main.rs")->historicalContext(evidence_kind:"file_relation")
selectArtefacts(path:"rust-app/src/main.rs")->contextGuidance(category:"decision",kind:"architectural_boundary")
Current DSL limitations:
- compiles only against the slim endpoint
- supports one explicit terminal stage at a time
- defaults to selecting
overview ->select(overview,schema)is supported for the chosen stage- the DSL stage name remains
deps(), but it compiles to the raw GraphQLdependencies(...)field onselectArtefacts - aggregate
selectArtefacts { overview }is not yet available through the DSL
Recommended Agent Flow
For tool-using agents, the lowest-error pattern is:
- Resolve the artefact set with
selectArtefacts(by: ...) - Ask for aggregate
overview - Choose the category worth expanding
- Query that category’s
items(first: ...)
That keeps the default call compact while still allowing full typed detail on demand.