Lola
Interview presentation

Hi, I'm Lola.
Software Engineer.

Duke University: B.S. Computer Science, Decision Sciences Certificate, Class of 2024.

Software Engineer at Apple: Web Platform Infrastructure, building AI infrastructure for internal teams.

The journey: Dominican Republic → Durham, NC → San Francisco, CA Dominican Republic Durham, NC Duke University San Francisco, CA Apple
The problem

Querying content from where he already works.

He can't query AppleWeb content in the AI Agent.

Current workflow
yoursite.example.com/admin/content
Drupal
Content
Structure
Appearance
People
Reports
Configuration
Content
TitleNode IDStatus
Campus impact: five years later1842Unpublished
Homecoming weekend recap1839Published
Research grant announcement1831Published
Q3 enrollment update1825Published
New library wing opens1818Published
Faculty spotlight: chemistry dept1802Published
‹ 1 2 3 4 5 ›
Agent Drupal UI Manual search Copy node ID Agent Analytics tool
Ideal workflow
claude.ai
Can I get all the articles about campus impact in 2017?
Claude
1842Campus impact: five years later
1774Community partnerships expand campus impact
1699Campus impact program: year one recap
How many views did the article with node 1842 get this month?
Claude
"Campus impact: five years later" (node 1842) had 1,204 views this month.
Approaches considered

Three ways to connect the agent.

  • Only surfaces published content
  • Search logic is a black box
  • Owned by another team's roadmap
  • Strong for thematic similarity, but still needs metadata filters for type, status, and date
  • Requires a synchronized index, authorization rules, and another retrieval system to operate
Chosen path
Model Context Protocol: a standard way for an agent to call outside tools and data, without a custom integration for every system.
  • Keeps the experience inside the agent
  • Reuses one protocol instead of one-off integrations
  • Can extend to the 2 other sites that'll want this too
Scope

The scope kept growing outward.

News site
Articles
+ Generic pages
+ Tweets
+ People site
+ IT tools site
Different entities
Iterations

Three attempts at getting this right.

The fastest thing to try first: let the agent talk to the database directly.

AI Agent
MySQL MCP
Decides the query
list_tables discover_schema
MySQL
Direct connection
Exposed database credentials
A read-only database user can prevent writes, but that does not reproduce Drupal's content-access rules
The model wrote raw SQL, which meant it could potentially corrupt the database
The model could still return content the current Drupal user was not authorized to see
Ran many queries and synthesized results. This wouldn't scale.

Move the query behind Drupal's own Views layer instead. The agent can no longer write SQL queries.

AI Agent
Fixed View MCP
search_articles(keywords, limit, status, author)
build_results_url(nids)
get_article(nid)
Views API
search_article get_article
Creating a view
Drupal · Views
Title, Node ID, Author
Published, Date, Keyword
Author, Referenced entity
Newest first
Table
How a question becomes a query
Build a view
In Drupal's UI
Export it
Loads it, reads exposed filters
Expose filters to the LLM
Via MCP instructions
LLM maps the prompt
Into those exact parameters
🔒 keyword 🔒 status 🔒 author
What the API does when a query runs
Load the view
article_search
Set exposed input
{keyword, status, author, …}
execute()
Return rows
Back to the agent
Could only create the views I had already hand built. This made the system too rigid.
Every time the stakeholder wanted to query on a new field or entity, I would have to manually change the view or add support for a completely new one. This was not sustainable or scalable.
New requirements didn't fit the shape.
Why was it valuable?
  • Learned the importance of Views
  • How they worked, and how to build them

Dynamically build views based on available entities, bundles, and fields. The agent decides what to expose and filter, and the server dynamically builds the view in PHP.

AI Agent
Dynamic Views MCP
Progressive discovery
Views API
Dynamic: any entity, any bundle
Not raw SQL. Not just values in a fixed view. A small JSON spec.
{ "entity_type": "node", "bundle": "article",
  "filters": [
    { "field": "field_article_type", "operator": "or", "value": ["promo_tile"] }
  ],
  "limit": 5 }
MCP tools
1explain_viewsViews 101: a primer sent once per session
2get_entitiesWhich entities the admin has chosen to expose
3get_bundlesThe bundles within that entity
4get_fieldsThe filterable fields within that bundle
5build_view_specComposes the filter set into a spec
Progressive schema discovery
Entity type
node
The broad Drupal object family.
Bundle
article · generic page · tweet
The content shape within the entity.
Fields
title · date · status · references
Only approved fields become queryable.
The pipeline
validate
The gate
compile
Into the internal spec
build
Interprets the spec
run
Executes, dedupes
results
Returns rows, discards view
validate_spec returns [] when clean; otherwise the endpoint replies 422 with errors. Mistakes come back as data the agent reads and retries on, not exceptions
compile_spec derives everything entity-specific from entity_get_info(), and injects the bundle as a filter the agent can never set itself
_dynamic_views_build interprets the spec with views_new_view(), always adds the base id column, then forces the guardrails
dynamic_views_run executes and dedupes ids, computing an access-scoped total
dynamic_views_results returns rows of {id, bundle, title, fields}. The view is never saved, only built for that one request
The hard parts
Tables don't explain themselves. node alone doesn't say it holds articles and generic pages
Send extra context: descriptions attached to entities and fields
Can't send the whole schema. The payload gets too big, and most of it is noise
Hand-curate which entities, bundles, and fields are actually queryable
Outcome first

A working pilot in a production-like environment.

Stakeholder asks naturally
Topic + type + date
Drupal returns allowed content
IDs ready for composition
Adobe MCP answers next
One agent conversation
Use Observe Collect feedback Improve retrieval
Reflection

The pilot works. Real usage is showing us what to improve.

ACB/content-builder retrieval

A referenced-content bug exposed where relationship handling still needs to be more robust.

Entities beyond nodes

Generalize discovery and results so the system works across the other sites' entity models.

Better schema descriptions

Add descriptions to entity types, bundles, and fields so the model selects the right data with less trial and error.

Feedback as a product mechanism

Capture what the stakeholder likes, what fails, and why. Use that evidence to evaluate usefulness and prioritize improvements.

What I learned
Bigger picture