TypeDB 3.x Driver Guide
Critical gotchas and code examples for working with the TypeDB 3.x Python driver — no sessions, .resolve(), fetch syntax, and has-clause chaining.
TypeDB 3.x Driver Guide
TypeDB 3.x introduced breaking changes from 2.x. This guide covers the critical differences that will trip you up, with working Python code examples using the typedb-driver 3.8.0 package.
Connecting to TypeDB
from typedb.driver import TypeDB, Credentials, DriverOptions
driver = TypeDB.driver(
'localhost:1729',
Credentials('admin', 'password'),
DriverOptions(is_tls_enabled=False)
)
The driver connects over gRPC on port 1729. TLS is disabled for cluster-internal communication. For production deployments behind a load balancer, set is_tls_enabled=True.
No Sessions (Critical Change)
In TypeDB 2.x, you opened a session on a database and then opened transactions within that session. TypeDB 3.x removed sessions entirely. You open transactions directly on the driver.
# TypeDB 2.x (WRONG — will not work)
session = driver.session('ffo', SessionType.DATA)
tx = session.transaction(TransactionType.READ)
# TypeDB 3.x (CORRECT)
tx = driver.transaction('ffo', TransactionType.READ)
Transaction types are TransactionType.READ, TransactionType.WRITE, and TransactionType.SCHEMA.
Must Call .resolve() on Query Results
Queries in TypeDB 3.x return Promises, not results. You must call .resolve() to get the actual answer. Forgetting this is the single most common bug.
# WRONG — answer is a Promise, not results
answer = tx.query('match $c isa cluster; fetch { $c.* };')
# CORRECT — .resolve() executes the query and returns the answer
answer = tx.query('match $c isa cluster; fetch { $c.* };').resolve()
Answer Types
The resolved answer object has type-checking methods to determine what kind of result you got:
answer = tx.query('match $c isa cluster; fetch { $c.* };').resolve()
if answer.is_concept_documents():
# fetch queries return documents (plain Python dicts)
for doc in answer.as_concept_documents():
print(doc) # {'name': 'geo-prod-01', 'environment': 'prod', ...}
elif answer.is_concept_rows():
# match queries (without fetch) return rows
for row in answer.as_concept_rows():
cols = list(row.column_names())
entity = row.get('c') # returns a concept object, not a dict
elif answer.is_ok():
# some write queries return ok
pass
Fetch queries return concept_documents — plain Python dicts you can use directly.
Match queries (without fetch) return concept_rows — each row contains concept objects that need further processing to extract values.
Fetch Syntax Uses Curly Braces
TypeDB 3.x changed the fetch syntax. It uses curly braces, not the 2.x colon-star syntax.
# TypeDB 3.x (CORRECT)
match $c isa cluster; fetch { $c.* };
# TypeDB 2.x (WRONG — will not parse)
match $c isa cluster; fetch $c: *;
Named fetches also use curly braces:
match $c isa cluster, has name $n;
fetch { "cluster_name": $n };
limit and offset Come Before fetch
In TypeDB 3.x, limit and offset clauses must appear between the match clause and the fetch clause. Putting them after fetch is a syntax error.
# CORRECT — limit/offset between match and fetch
match $c isa cluster; limit 10; offset 5; fetch { $c.* };
# WRONG — limit after fetch
match $c isa cluster; fetch { $c.* }; limit 10;
has Clauses Chain With Commas
In TypeDB 3.x, has clauses chain directly after the isa clause using commas. Do not repeat the variable.
# CORRECT — has clauses chain with commas
match $e isa cluster, has name "geo-prod-01", has environment "prod";
# WRONG — repeating the variable
match $e isa cluster, $e has name "geo-prod-01";
# WRONG — separate statements
match $e isa cluster; $e has name "geo-prod-01";
Multiple has clauses continue the comma chain:
match $e isa cluster,
has name "geo-prod-01",
has environment "prod",
has classification "IL4",
has fips_enabled true;
fetch { $e.* };
Schema Queries
To list entity or relation types from the schema, use the entity and relation keywords in a SCHEMA transaction:
tx = driver.transaction('ffo', TransactionType.SCHEMA)
answer = tx.query('match entity $x;').resolve()
# Returns all entity types defined in the schema
answer = tx.query('match relation $x;').resolve()
# Returns all relation types defined in the schema
These queries run in schema transactions, not read transactions.
Inference Is Always On
TypeDB 3.x removed the inference toggle. Inference rules are always active. There is no options.infer(True) or equivalent.
This means every query automatically includes derived relationships. For example, if you query for controls applicable to a cluster, you will get both explicitly asserted controls and controls inferred through boundary and framework relationships.
# Both of these return the same results — inference is always on
results_explicit = tx.query('match ...').resolve()
results_inferred = tx.query('match ...').resolve() # no way to disable inference
The FFO MCP server has a query_with_inference method for API compatibility, but it delegates to the same query method internally.
Write Transactions
Write transactions require an explicit commit(). If you close the transaction without committing, changes are rolled back.
tx = driver.transaction('ffo', TransactionType.WRITE)
try:
answer = tx.query('insert $x isa cluster, has name "new-cluster";').resolve()
tx.commit() # MUST commit or changes are lost
except Exception:
tx.close() # rollback on error
raise
Delete Queries
Deletes also use write transactions:
tx = driver.transaction('ffo', TransactionType.WRITE)
try:
tx.query(
'match $e isa cluster, has name "old-cluster"; delete $e;'
).resolve()
tx.commit()
except Exception:
tx.close()
raise
Updating Attributes
TypeDB does not have an UPDATE operation. To change an attribute value, delete the old attribute and insert the new one in the same write transaction:
tx = driver.transaction('ffo', TransactionType.WRITE)
try:
# Delete old value
tx.query(
'match $e isa cluster, has name "geo-prod-01"; '
'$e has environment $old_env; '
'delete $e has environment $old_env;'
).resolve()
# Insert new value
tx.query(
'match $e isa cluster, has name "geo-prod-01"; '
'insert $e has environment "staging";'
).resolve()
tx.commit()
except Exception:
tx.close()
raise
Database Management
# List all databases
databases = driver.databases.all()
db_names = [db.name for db in databases]
# Check if a specific database exists
if 'ffo' not in db_names:
raise RuntimeError('FFO database not found')
QueryOptions
Optional query configuration:
from typedb.driver import QueryOptions
opts = QueryOptions()
opts.include_instance_types # Optional bool — include type info in results
opts.prefetch_size # Optional int — tune result prefetching
result = tx.query('match $c isa cluster; fetch { $c.* };', opts).resolve()
Complete Working Example
Putting it all together — a script that connects to TypeDB, queries clusters, and prints results:
from typedb.driver import TypeDB, Credentials, DriverOptions, TransactionType
# Connect
driver = TypeDB.driver(
'localhost:1729',
Credentials('admin', 'password'),
DriverOptions(is_tls_enabled=False)
)
# Query all clusters
tx = driver.transaction('ffo', TransactionType.READ)
try:
answer = tx.query(
'match $c isa cluster; limit 10; fetch { $c.* };'
).resolve()
if answer.is_concept_documents():
for doc in answer.as_concept_documents():
print(f"Cluster: {doc.get('name', 'unknown')}")
print(f" Environment: {doc.get('environment', '-')}")
print(f" Classification: {doc.get('classification', '-')}")
print()
finally:
tx.close()
# Clean up
driver.close()
Common Errors and Fixes
| Error | Cause | Fix |
|---|---|---|
AttributeError: 'Promise' object has no attribute 'is_concept_documents' |
Forgot .resolve() |
Add .resolve() after tx.query(...) |
TypeQL syntax error at 'fetch' |
Using 2.x fetch syntax | Change fetch $x: *; to fetch { $x.* }; |
TypeQL syntax error at 'limit' |
limit after fetch | Move limit N; before fetch |
TypeQL syntax error near '$e' |
Repeating variable in has clause | Chain has clauses: $e isa X, has a "1", has b "2" |
Session not found or similar |
Using 2.x session API | Use driver.transaction(db, type) directly |
Transaction is already closed |
Using tx after commit/close | Open a new transaction |
Database 'ffo' not found |
Wrong database name or TypeDB not loaded | Check driver.databases.all() |