Agent-tool runs
Agent-tool runs: the run directory of format 2, its call log, its lock and its replay.
An agent in its own harness builds a graph through the package's tools. Each tool call that changes
the run is one write: it takes the run's lock, applies an operation to the current state, and
commits. The commit point is one line appended to calls.jsonl, so the log is the record of truth
and every other file is derived from it:
- the new state is written to
state.json.tmp; - the call's line is appended to
calls.jsonland flushed to disk; state.json.tmpis renamed tostate.json, andmanifest.jsonis rewritten the same way.
A process that dies before step 2 leaves no trace; one that dies after it leaves a state.json
that names fewer calls than the log, which the next tool call finds and rebuilds by applying the
logged calls to the graph start_run ingested (ingested.json). Ids are allocated from the
state under the lock, so the calls of several agents, applied in log order, give the same ids again.
The layout::
<run>/
manifest.json format "credencegraph-extract-run", version 2
calls.jsonl every write, in the order it took effect
state.json the state after the last call, and how many calls it reflects
ingested.json the graph start_run ingested, the start of every rebuild
rubric.toml byte copy of the rubric
cited/ byte copies of the cited works, made by start_run
checks/c-NNN/ each check's inputs, output and log, written from the state
source/ a copy of the document, only with store_source
sources/ the bytes of each fetched source, named by digest, only with store_source
graph.json the graph, only while the run is finished
rejections.json every refused record, only while the run is finished
report.json coverage, untied citation checks and checks made with a model their type was
not fitted with, only while the run is finished
replay re-ingests the document and applies every logged call again, checking each call's result
digest; the graph it ends with must be byte-identical to the run's. The log records no local path:
a file is named by its name and digest.
Context
dataclass
¶
What an operation may read beside the state: the run and its fixed inputs.
Attributes:
| Name | Type | Description |
|---|---|---|
run_dir |
Path
|
The run directory. |
run_id |
str
|
The run's id. |
rubric |
Rubric
|
The run's rubric. |
call |
int
|
The number of the call being applied, from 1 for |
cited |
Mapping[str, str]
|
The digest of each file of the run's copy of the cited works, as |
model |
str | None
|
The model the call reports. |
replaying |
bool
|
Whether the call is applied by |
sources |
Path | None
|
Where a replay finds fetched sources the run did not store, as files named by the hex of their digest. |
Source code in src/credencegraph_extract/session.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
State
dataclass
¶
What a run holds between tool calls.
Attributes:
| Name | Type | Description |
|---|---|---|
graph |
Graph
|
The graph so far. |
rejections |
tuple[Mapping[str, Any], ...]
|
Every refused record or proposal, with the call that sent it. |
finished |
bool
|
Whether the last write was |
files |
Mapping[str, str]
|
The files of the checks run, by path in the run ( |
Source code in src/credencegraph_extract/session.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |
current_state(run_dir)
¶
Return the run's state, rebuilt from the log when state.json does not reflect all of it.
The caller holds the lock.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Returns:
| Type | Description |
|---|---|
State
|
The state after every logged call. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the run directory is malformed or incomplete. |
Source code in src/credencegraph_extract/session.py
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | |
get_state(run_dir)
¶
Return what a run holds now, for an agent deciding its next call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Every node's id, type and statement, with its assessment where it has one; the relations; the |
dict[str, Any]
|
refused records so far; how many calls the log holds; and whether the run is finished. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the run directory is malformed or incomplete. |
Source code in src/credencegraph_extract/session.py
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | |
lock(run_dir, timeout=LOCK_TIMEOUT)
¶
Hold the run's lock: one tool call at a time, across processes.
The operating system releases the lock when its process exits, so a crashed agent leaves none
behind. A call that cannot take the lock within timeout seconds reports the run busy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
timeout
|
float
|
How long to wait, in seconds. |
LOCK_TIMEOUT
|
Yields:
| Type | Description |
|---|---|
None
|
Nothing; the lock is held until the block ends. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the lock is not free within |
Source code in src/credencegraph_extract/session.py
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |
lock_holder(run_dir)
¶
Return who holds a run's lock, or None when no tool call does.
The lock is the operating system's: it is released when its process exits, so a crashed agent leaves none behind, and only a live process (a hung one, say) can hold it. A free lock's leftover owner record, from a process that died holding it, is removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
|
dict[str, Any] | None
|
or |
Raises:
| Type | Description |
|---|---|
RunError
|
If the directory is not a run. |
Source code in src/credencegraph_extract/session.py
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | |
operation(name)
¶
Register a write tool's operation under its name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The tool's name, as the call log records it. |
required |
Returns:
| Type | Description |
|---|---|
Callable[[Operation], Operation]
|
A decorator registering the operation. |
Source code in src/credencegraph_extract/session.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
read_calls(run_dir)
¶
Read the call log.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
The calls, in the order they took effect. |
Raises:
| Type | Description |
|---|---|
RunError
|
If a line is not a call object, or the calls are not numbered 1, 2, … from |
Source code in src/credencegraph_extract/session.py
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | |
read_manifest(run_dir)
¶
Read a format-2 run's manifest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The manifest. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the directory is not a run of this format and version. |
Source code in src/credencegraph_extract/session.py
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | |
reconcile(run_dir)
¶
Bring a run's state, manifest and outputs back in line with its call log, under the lock.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Raises:
| Type | Description |
|---|---|
RunError
|
If the run directory is malformed or incomplete. |
Source code in src/credencegraph_extract/session.py
696 697 698 699 700 701 702 703 704 705 706 707 | |
recorded_graph(run_dir)
¶
Return the run's graph after every logged call, as replay returns it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
The graph, as the core serialises it, with a final newline. |
Source code in src/credencegraph_extract/session.py
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 | |
replay(run_dir, *, source=None, sources=None)
¶
Re-ingest a run's document and apply every logged call again, without the network.
Each call's result must have the digest the log recorded; the graph the last call leaves is
returned, as state.json holds it, for the caller to compare with the run's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
source
|
Path | None
|
The document, for a run that did not store it. |
None
|
sources
|
Path | None
|
The fetched sources the run did not store, as files named by their digest. |
None
|
Returns:
| Type | Description |
|---|---|
bytes
|
The rebuilt graph, as the core serialises it, with a final newline. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the run directory is malformed or incomplete, the document, rubric or a cited copy differs from what the run recorded, or a call's result differs from its record. |
Source code in src/credencegraph_extract/session.py
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 | |
rubric_problems(rubric)
¶
Return why a rubric cannot be used for an agent-tool run, or nothing if it can.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rubric
|
Rubric
|
The rubric. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Every problem: an edge rule that creates a relation other than |
list[str]
|
|
Source code in src/credencegraph_extract/session.py
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 | |
stamp(graph, before, mark)
¶
Stamp every node of graph that is new or changed since before with attributes.extraction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph
|
Graph
|
The graph after a change. |
required |
before
|
Graph
|
The graph before it. |
required |
mark
|
Mapping[str, Any]
|
The stamp, such as |
required |
Returns:
| Type | Description |
|---|---|
Graph
|
The stamped graph. |
Source code in src/credencegraph_extract/session.py
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
start_run(source, rubric, run, *, harness, model, agent=None, note=None, document=None, cited=None, store_source=False)
¶
Start a run: check the rubric, ingest the document, copy the cited works, and log the call.
Everything is read and checked before the run directory is written, so a rubric the tools cannot use, an unreadable document or a cited directory holding a link leaves nothing behind.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
The document's main |
required |
rubric
|
Path
|
The rubric file. |
required |
run
|
Path
|
The run directory to create; it must not exist or be empty. |
required |
harness
|
str
|
The agent harness, as it reports itself. |
required |
model
|
str
|
The model making the call. |
required |
agent
|
str | None
|
A name for the agent. |
None
|
note
|
str | None
|
Free text kept with the call. |
None
|
document
|
str | None
|
The document id of every anchor; the source's file name by default. |
None
|
cited
|
Path | None
|
The directory of cited works, each a file named by its bibliography key; copied into the run with each file's digest, and the copy is the only one the citation tool reads. |
None
|
store_source
|
bool
|
Copy the document into the run. |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The run's id, the chunks, the document types with their form fields and edge rules, the hedge |
dict[str, Any]
|
phrases, the check types the tools run, and those the rubric declares but the tools do not. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the run directory is in use, the rubric cannot be used, the document cannot be read, or the cited works are not plain files. |
Source code in src/credencegraph_extract/session.py
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 | |
versions()
¶
Return the versions a run depends on: Python, the core, this package and sympy.
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
The versions by name. |
Source code in src/credencegraph_extract/session.py
185 186 187 188 189 190 191 192 193 194 195 196 | |
write(run_dir, tool, args, *, model, agent=None, note=None)
¶
Make one write to a run: apply a tool's operation under the lock and commit it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run_dir
|
Path
|
The run directory. |
required |
tool
|
str
|
The tool, a registered operation. |
required |
args
|
Mapping[str, Any]
|
Its arguments, as JSON values. |
required |
model
|
str
|
The model making the call, as the harness reports it. |
required |
agent
|
str | None
|
A name for the agent, for runs with several. |
None
|
note
|
str | None
|
Free text kept with the call, never used in inference. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The tool's result. |
Raises:
| Type | Description |
|---|---|
RunError
|
If the tool is unknown, the run is busy or malformed, or the operation refuses the call as a whole. |
Source code in src/credencegraph_extract/session.py
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | |