Server-Side Agent Let GraphJin run the catalog-first discovery loop for you and return a typed answer through one MCP tool and one REST endpoint. agentic guide agentic/server-agent agentic/server-agent.md

Server-Side Agent

Let GraphJin run the catalog-first discovery loop for you and return a typed answer through one MCP tool and one REST endpoint.

The server-side agent runs GraphJin’s catalog-first discovery loop inside GraphJin and exposes it as a single MCP tool, ask_graphjin_agent, and a single REST endpoint, POST /api/v1/agent. Instead of your client chaining query_catalogquery_catalog(id)validate_where_clauseexecute_saved_query itself, you send one instruction and GraphJin discovers, validates, executes, and returns a typed, evidence-backed answer.

It is optional and off by default. Use it when you want GraphJin to orchestrate discovery in one governed, caller-scoped, auditable call; use the MCP tools directly when you want to drive the loop step by step yourself.

Enable it

The agent block lives in agentic.yml, which loads when the environment is agentic:

Shell
GO_ENV=agentic graphjin serve --path ./config
YAML
# agentic.yml
agent:
  enabled: true
  provider: openai
  model: gpt-4.1-mini
  api_key_env: OPENAI_API_KEY

See the Config Reference for all options.

How it works

The agent is an RLM (reasoning-with-code) loop, not a tool-calling loop. The model writes JavaScript that calls the discovery and execution tools as runtime globals inside a sandbox — query_catalog({...}), graphql_help({...}), validate_where_clause({...}), execute_saved_query({...}), and final({...}). GraphJin runs that code, feeds results back, and the typed result is parsed from the model’s key: value output.

This means the only model requirement is that it is good at code generation and follows the key: value output format. It does not need provider function-calling or structured-output/JSON modes, so any OpenAI-compatible chat-completions endpoint works (see OpenAI-compatible endpoints).

Every answer is grounded in observed evidence. Go-side protocol guards enforce the catalog-first contract — for example a saved query may only run after its saved_query catalog row has been inspected — and downgrade an answered result to blocked (with evidence) when a required step was skipped. Models cannot talk their way past the guards; only real tool results count.

Modes

ModeWhat the agent may do
safe (default)Discover, validate, and run approved saved queries/mutations. No raw GraphQL.
discovery_onlyRead-only: catalog/help/validation only. No execution.
raw_allowedAdds execute_graphql for composed queries — only when agent.allow_raw_graphql and mcp.allow_raw_queries are both set.

Role-aware guidance

The agent is caller-aware. From the request’s identity it derives a capability profile (limited to the fixed gj_* system roots — never application tables) and picks a focused guidance skill for the task: per domain (data, code, workflow, admin) and per operation (read vs write, chosen from the instruction). An admin asking to change config is guided toward the gj_config recipe flow; a normal user is guided through plain data discovery.

Skills only shape the guidance the model sees. They never grant access. What any caller can actually read or write is enforced by GraphJin core (roles + row-level security), exactly as for a direct GraphQL request — the agent always runs as the caller.

Verified by TestSelectSkill agent/skills_test.go:88
Verified by TestHasWriteIntent agent/skills_test.go:65

Request and response

Request fields: instruction (required), and optional context, namespace, mode, max_steps, return_trace.

Response fields: status (answered | needs_clarification | blocked | error), answer, and optional data, evidence, actions, next, errors, usage, trace, trace_id.

REST

Shell
curl -sS http://localhost:8080/api/v1/agent \
  -H 'content-type: application/json' \
  --data '{"instruction":"What production work should we prioritize next?","mode":"safe"}'

MCP

JSON
{
  "name": "ask_graphjin_agent",
  "arguments": {
    "instruction": "What production work should we prioritize next?",
    "mode": "safe"
  }
}
Verified by TestAskGraphJinAgentMCPSchema serv/agent_handler_test.go:347

OpenAI-compatible endpoints

Point the agent at any OpenAI-compatible chat-completions endpoint (vLLM, Ollama’s OpenAI endpoint, OpenRouter, Together, LM Studio, Groq, …) with base_url:

YAML
agent:
  enabled: true
  provider: openai            # or: openai-compatible
  model: <model-name>
  api_key_env: OPENAI_API_KEY # must hold a non-empty value (a dummy is fine for keyless local endpoints)
  base_url: https://your-endpoint/v1

Because the loop is driven by generated code rather than provider tool-calling, the practical requirement is a model that codegens well — not one with native function-calling support.

When to use it

  • Use the server-side agent to hand GraphJin a goal and get a typed answer in one call, with discovery, validation, and guardrails handled server-side and scoped to the caller.
  • Use MCP tools directly when your own agent should own the loop and make each discovery/execution decision itself.
Docs