cswork / libraryOpen practice workspace

Articles · Glean

Glean Software Engineer Interview Guide 2026: Coding, Enterprise Search, RAG, and System Design

Prepare for Glean software engineer interviews with coding, enterprise search, a tested RAG trace, access revocation, citations and role-specific study plans.

A Glean software engineer interview is easier to prepare for when “enterprise AI” becomes a concrete engineering problem. A search result can be relevant and still be wrong to use: it may belong to another tenant, contain an obsolete policy or remain in an index after deletion. An answer can cite the right document while inventing the number it attributes to that document.

Prepare to write correct code, explain those distinctions and show evidence when something fails. This guide retains the role mapping and permission-aware design focus, then adds a complete retrieval fixture, executable checks and a resolved answer trace. The documents, scores and code are original teaching material, not Glean internals or a private interview prompt.

What the current public evidence supports

Glean’s current Software Engineer, AI/ML Infrastructure posting describes work across search, generative AI, RAG, query and document understanding, evaluation and infrastructure. It asks for maintainable, tested code and customer-focused problem solving. It also states that the interview process includes a brief AI-focused exercise or discussion; prior Glean experience is not required.

That statement does not define a universal round sequence, assessment cutoff or permission to use AI in every coding session. Confirm the format, timing, language and permitted tools for your invitation. Prepare one example of how you used an AI tool, what you independently verified and what judgment remained yours. Keep confidential employer or interview material out of tools unless explicitly authorized.

The older job link used by this guide now redirects to the openings board. The sources below link the current posting rather than continuing to call the expired page current.

Glean’s Search FAQ describes respecting connected-source permissions and incorporating content, activity and identity information. Its Assistant documentation distinguishes company, web and model knowledge, with source controls and administrator-dependent availability. Do not confuse internal enterprise search with every Assistant knowledge mode, or assume that every answer uses company documents.

For the exercise below, the product requirement is deliberately narrower: answer an internal policy question only from current, authorized company evidence. Glean describes reflecting connector permission changes quickly; these sources do not establish a numerical zero-lag guarantee. Our local authority gives the exercise a testable boundary, rather than pretending to reproduce connector behavior.

Choose the work you need to defend

Role emphasisPractice outputFollow-up to rehearse
Search qualityRanked candidates, relevance labels and an error sliceWhy did the expected document disappear?
Assistant or agentsEvidence contract, citations and refusal behaviorWhat prevents an unsupported claim or unsafe action?
APIs and context platformIdentity propagation, versioned contracts and retriesWhat happens when access changes during a request?
AI/ML infrastructureServing capacity, timeouts and reproducible releasesWhich dependency failed, and what still works?
Product or full-stackState transitions, accessibility and user feedbackHow does a denied or incomplete answer appear?

These are study routes. Match them to your actual team instead of assuming that every software engineer interview has the same RAG depth. For ordinary coding, practice maps, heaps, intervals, graphs and streaming state with an explicit invariant, edge tests and complexity analysis.

Worked fixture: a travel-policy answer

Original scenario. Bob belongs to tenant A. He asks, “What is our standard travel cap?” The trusted source contains the following documents. Access is an explicit user set in this small model; a real enterprise service must resolve groups, inherited permissions and connector identities.

DocumentCurrent sourceBob’s accessIndexed candidate
otherTenant B, revision 1, $900 policyWrong tenantScore 0.99
deletedNo longer existsNoneStale result, score 0.98
execTenant A, revision 1, executive cap $400Alice onlyScore 0.97
policyTenant A, revision 2, standard cap $150Alice and BobOld revision 1, score 0.96

Every initial candidate must be excluded. The tenant-B document cannot cross the tenant boundary. The deleted result has no live source. The executive policy is not accessible to Bob. The standard policy has the right document ID but the wrong revision.

The index’s old policy is not supplied as trusted context. If the product has a separate authorized source-fetch fallback, define and test it explicitly. This exercise abstains until the current revision is indexed; changing a prompt cannot repair missing current evidence.

Now add policy revision 2 with score 0.95. It becomes the only eligible passage despite having the lowest raw score. Filter before applying the final context limit. Keeping only the top two raw candidates and filtering afterward would incorrectly return nothing.

Runnable current-evidence gate

Save the code as retrieval_case.py and run python retrieval_case.py. It uses Python’s standard library. Identities are trusted server inputs in the harness; accepting a browser-supplied tenant or username would not authenticate a real request.

from dataclasses import dataclass, replace
from threading import RLock

@dataclass(frozen=True)
class Doc:
    tenant: str
    revision: int
    text: str
    users: frozenset

class EvidenceStore:
    # Trusted server identity and authoritative local source; not an HTTP API.
    def __init__(self, docs):
        self.docs = dict(docs)
        self.lock = RLock()
        self.available = True

    def eligible(self, tenant, user, doc_id, revision):
        if not self.available:
            raise ConnectionError('authorization source unavailable')
        doc = self.docs.get(doc_id)
        if doc is None or doc.tenant != tenant or user not in doc.users:
            return None
        return doc if doc.revision == revision else None

    def context(self, tenant, user, candidates, k=2):
        if type(k) is not int or k < 1:
            raise ValueError('positive integer k required')
        with self.lock:
            allowed = []
            seen = set()
            for doc_id, revision, score in sorted(
                    candidates, key=lambda row: (-row[2], row[0], row[1])):
                if doc_id in seen:
                    continue
                doc = self.eligible(tenant, user, doc_id, revision)
                if doc:
                    seen.add(doc_id)
                    allowed.append((doc_id, revision, doc.text))
            return allowed[:k]

    def deliver(self, tenant, user, evidence, proposed):
        # Exact quotation only: no semantic judge or general LLM generation.
        with self.lock:
            for doc_id, revision, text in evidence:
                doc = self.eligible(tenant, user, doc_id, revision)
                if doc and doc.text == text and proposed == text:
                    return {'answer': text, 'citation': (doc_id, revision)}
            return {'answer': 'No current authorized supporting passage.',
                    'citation': None}

    def revoke(self, doc_id, user):
        with self.lock:
            doc = self.docs[doc_id]
            self.docs[doc_id] = replace(doc, users=doc.users - {user})

    def replace_source(self, doc_id, doc):
        with self.lock:
            if doc is None:
                self.docs.pop(doc_id, None)
            else:
                self.docs[doc_id] = doc

def fixture():
    users = frozenset({'alice', 'bob'})
    return EvidenceStore({
        'policy': Doc('A', 2, 'Standard travel cap: $150.', users),
        'exec': Doc('A', 1, 'Executive travel cap: $400.', frozenset({'alice'})),
        'other': Doc('B', 1, 'Tenant B travel cap: $900.', users),
    })

if __name__ == '__main__':
    source = fixture()
    stale = [('other', 1, .99), ('deleted', 1, .98),
             ('exec', 1, .97), ('policy', 1, .96)]
    print('stale:', source.context('A', 'bob', stale))
    fresh = stale + [('policy', 2, .95)]
    evidence = source.context('A', 'bob', fresh)
    print('fresh:', evidence)
    print('unsupported:', source.deliver('A', 'bob', evidence,
                                       'Standard travel cap: $250.'))
    print('supported:', source.deliver('A', 'bob', evidence, evidence[0][2]))
    source.revoke('policy', 'bob')
    print('revoked cached evidence:', source.deliver(
        'A', 'bob', evidence, evidence[0][2]))

The initial stale result is empty. The fresh result is exactly ('policy', 2, 'Standard travel cap: $150.'). A proposed $250 answer returns no citation and an explicit refusal. The exact $150 quotation returns citation ('policy', 2). After Bob is revoked, the same cached evidence is rejected at delivery.

The quotation gate is intentionally strict. It accepts one complete source text, not a free-form summary, partial citation or multi-document synthesis. That makes the example deterministic. It does not establish that arbitrary generated answers are semantically faithful, or that a quoted passage is relevant just because it matches text.

Where the failure occurs changes the repair

Observed traceClassificationFirst repair
Current policy absent; only revision 1 retrievedIngestion or retrieval freshnessRepair connector/index publication and verify revision 2 appears
Current policy retrieved but dropped by raw top-kFiltering/context selectionSelect final k after authorization and version validation
Revision 2 is in context; answer claims $250Unsupported answerReject the claim; inspect context handling and generation
A cached answer survives Bob’s revocationAuthorization boundary failureRevalidate current access at response delivery
Authorization source is unavailableDependency failureFail closed; do not infer access from an old score or citation

The code resolves the supported case with a current quotation. A missing or unsupported case says that no current authorized supporting passage is available. It does not expose the title or text of rejected documents to Bob. The fixture table is public teaching data; production diagnostic logs containing rejected IDs or content require their own access controls.

Keep retrieval traces internally useful and minimally revealing. Record request identity from the authenticated boundary, candidate IDs/revisions, filter reasons, final context IDs, generation version and citation validation. Avoid logging complete sensitive passages by default. A debugging dashboard must not become an easier path around the search permissions it measures.

Revocation is a timing problem too

Checking access when a request enters the queue is insufficient. A request may wait while the source changes. This harness checks eligibility while constructing context, then checks it again under the source lock before returning the response object. Permission and document changes use that same lock.

The tests pause a request after retrieval, apply a revocation, deletion, revision update or tenant move, then let delivery proceed. All four reject the old evidence. The guarantee ends at that delivery check: a later revocation cannot retract bytes already sent. In a real service, define the response/streaming boundary and the consistency contract between source permissions and local authorization state.

Model invocation would sit outside this local lock, followed by another current-access check. The harness does not invoke a model. If access is revoked while an authorized passage is already being processed, withholding the final answer does not erase that earlier processing. Choose an approved model boundary and data-handling policy before passing company text to it.

Cache isolation also needs two layers. Tenant, principal and relevant policy/index versions help avoid accidental reuse across users. Current authorization and document-version checks still govern serving a cached answer. A user-specific cache key alone cannot make a previously permitted answer safe after access changes.

What the executed checks cover

The local harness passed 3,611 checks. Across 1,200 randomized cases, an independent per-document reference selects eligible current documents, compares ordering and verifies citations. Candidate shuffling must preserve the result, including score ties. Duplicated candidates and stale revisions must not create extra context entries.

Four staged threaded scenarios change access or source state between retrieval and delivery. Additional checks cover authorization unavailability at both boundaries, empty candidates and invalid context limits. These checks establish behavior for this Python model. They do not exercise Glean, a vector index, connector lag, HTTP authentication, persistent state or distributed races.

Sorting costs O(n log n) for n candidates; the scan and authority lookups cost O(n) in this local dictionary model. The implementation collects eligible results before slicing to k, using O(n) intermediate space. For large candidate streams, a bounded heap can reduce retained context, but authorization and version filtering must preserve the selection contract. Distributed permission checks introduce latency and batching decisions that this local code does not measure.

Expand it into an enterprise-search design

Draw ingestion separately from serving. Ingestion needs stable document identity, ordered source changes, retries, deletion handling and versioned publication. Serving needs authenticated tenant binding, bounded retrieval, current access checks, context construction, answer validation and a safe fallback.

Do not describe “freshness” as one clock. Measure source-event delay, connector processing, index publication and authorization-state age separately. Keep deletion tombstones until all consumers can no longer resurrect an old event. If a connector retries an earlier update after deletion, ordering or revision checks must reject that stale update.

Measure retrieval quality on authorized, current labels, not a global corpus that rewards hidden documents. Track evidence recall, citation support, appropriate abstention, unauthorized context, latency and cost as separate axes. Slice by tenant, connector and document churn. A pooled improvement can hide a failure for newly revoked users.

Treat retrieved instructions as data. A document saying “ignore access checks” must not alter the authorization service or acquire tool privileges. The exact-quote harness has no tools and proves no general prompt-injection defense. An agentic extension needs typed tool contracts, independently enforced identity, bounded actions and tests that show malicious source text cannot change authority.

For release decisions, start with a frozen regression set plus a rolling freshness set. Require permission tests to pass, compare retrieval and answer quality with the baseline, then canary the changed slice. Roll back the changed index/model/prompt component when evidence identifies it; swapping an embedding model before diagnosis can add another regression.

Rehearse with reviewable outputs

Spend the first session confirming your invitation and selecting the relevant study route. In the next two sessions, run the fixture, explain each rejected document and add one independent test. Then draw ingestion and serving, including the source of authorization truth and a model timeout fallback.

Use another session for evaluation: explain which trace distinguishes missing evidence from unsupported generation, and how you would prove a fix on the affected slice. Finish with a true project discussion and a mixed mock. State your own contribution, a rejected alternative, an observable result and what remained unresolved. Do not present this synthetic exercise as employment experience.

Frequently asked questions

Does Glean require an AI-focused interview exercise?

The current Software Engineer, AI/ML Infrastructure posting says candidates complete a brief AI-focused exercise or discussion; prior Glean experience is not required. Confirm what applies to your role. This does not authorize AI assistance in every coding round.

What should a Glean software engineer candidate practice?

Practice clear coding, permission-aware enterprise search, retrieval and answer evaluation, and a truthful project discussion. Adjust the balance to the exact posting: search quality, APIs, infrastructure and product work need different depth.

Why can a relevant document still be unsafe to retrieve?

Similarity does not establish access or freshness. A high-scoring result may belong to another tenant, be deleted, use an old revision or be inaccessible to the current user. Validate these conditions before passing content onward.

How can I tell retrieval failure from generation failure?

Record the expected source, retrieved IDs and revisions, authorized context and cited answer. Missing current evidence points toward retrieval or ingestion; an unsupported answer despite correct context points toward context handling or generation.

Does the Python example prove production RAG security?

No. It tests a trusted local authority and exact quotation, including four staged source/access changes before delivery. It does not test a language model, connector propagation, distributed authorization, group resolution or the Glean service.

Sources and scope

Checked October 9, 2026. The corpus, scores, retrieval implementation and checks are original local practice material. Public product documentation informs requirements; it does not disclose Glean’s internal implementation or guarantee your interview sequence.