Problem
LLM tool callers regularly pass GFQL chains as strings (literal Python expressions inside larger prompt JSON):
```python
g.gfql("[{'function':'encode_point_color','params':{'column':'type'}}]", ...)
```
Today pygraphistry expects a real `list[dict]` and these strings raise downstream as un-parseable AST.
Two paths forward
Option A — pygraphistry parses on input
`g.gfql` accepts `Union[str, list, dict, Chain]` and on `str` does `ast.literal_eval` (or `json.loads` after best-effort double-quote normalization) BEFORE handing to the chain validator. Existing chain validation runs against the parsed object.
Option B — explicit `graphistry.gfql.parse_chain(s) -> Chain`
Helper that consumers call to materialize a Chain object from a string. `g.gfql` keeps current strict typing.
Either resolves the recurring case where downstream tools (Louie's GraphAgent.gfql) had to grow their own parser:
```python
def _maybe_parse_gfql_query_string(query: str): ...
def _is_likely_structured_gfql_string(query: str): ...
def _raise_if_malformed_structured_radial_string(query: str): ...
```
(graphistrygpt/plugins/graphistry/tool.py)
Why upstream
Every LLM-driven consumer hits this. Centralizing the parser also means the deep validation in pygraphistry#1239 (axis row schema) has one canonical entry point.
Companion to #1239
If pygraphistry#1239 lands deep validation, accepting stringified chains is the natural next step — same shape contract, just unwrapped.
Filed via Louie graphistrygpt PR #2791 audit (findings.md upstream issue #5). Tracked at `graphistrygpt/plugins/graphistry/tool.py:_maybe_parse_gfql_query_string`.
Problem
LLM tool callers regularly pass GFQL chains as strings (literal Python expressions inside larger prompt JSON):
```python
g.gfql("[{'function':'encode_point_color','params':{'column':'type'}}]", ...)
```
Today pygraphistry expects a real `list[dict]` and these strings raise downstream as un-parseable AST.
Two paths forward
Option A — pygraphistry parses on input
`g.gfql` accepts `Union[str, list, dict, Chain]` and on `str` does `ast.literal_eval` (or `json.loads` after best-effort double-quote normalization) BEFORE handing to the chain validator. Existing chain validation runs against the parsed object.
Option B — explicit `graphistry.gfql.parse_chain(s) -> Chain`
Helper that consumers call to materialize a Chain object from a string. `g.gfql` keeps current strict typing.
Either resolves the recurring case where downstream tools (Louie's GraphAgent.gfql) had to grow their own parser:
```python
def _maybe_parse_gfql_query_string(query: str): ...
def _is_likely_structured_gfql_string(query: str): ...
def _raise_if_malformed_structured_radial_string(query: str): ...
```
(graphistrygpt/plugins/graphistry/tool.py)
Why upstream
Every LLM-driven consumer hits this. Centralizing the parser also means the deep validation in pygraphistry#1239 (axis row schema) has one canonical entry point.
Companion to #1239
If pygraphistry#1239 lands deep validation, accepting stringified chains is the natural next step — same shape contract, just unwrapped.
Filed via Louie graphistrygpt PR #2791 audit (findings.md upstream issue #5). Tracked at `graphistrygpt/plugins/graphistry/tool.py:_maybe_parse_gfql_query_string`.