Written for a CS student who wants to understand the Function Agent as code.
The Function Agent is a Java library that executes semantically described functions. A function description (by default in the Function Ontology, FnO) states what a function expects and returns, and maps it to an implementation, such as a static method of a Java class on the classpath or in a JAR file. Calling code asks an Agent to execute a function by its IRI with a set of Arguments; the agent loads the implementation lazily and invokes it. FnO compositions (functions built from other functions) are executed as well.
The project is a library: it has no command-line interface and no main entry point. It runs on the JVM only, keeps no state between calls, and supports compositions without recursion (see "Current limitations" in README.md).
- Maven coordinates:
be.ugent.idlab.knows:function-agent-java(seepom.xml); Java 21. - Source:
src/main/java/be/ugent/idlab/knows/functions/agent/. - Tests:
src/test/java/(JUnit 5), with fixtures insrc/test/resources/. - User documentation:
README.md(usage example, features, how composition execution works). Changes are recorded inCHANGELOG.md.
Every implementation request handled by an AI agent/LLM follows these constraints:
- If the request is a feature or bugfix:
- fix the specific failing case or issue named in the request;
- preserve existing passing behavior unless explicitly asked not to;
- add or update a regression test when needed.
- Leave staging and committing to the maintainer. Edit staged files freely: the maintainer stages what they reviewed, so the unstaged diff shows the new changes.
- Make the smallest coherent patch. A documentation error found along the way is fixed in the same patch.
- Leave the code leaner after every request: remove what the change makes redundant (duplicate tests, parameters and options that no longer do anything, helpers that duplicate each other, comments that only repeat the code), and reuse shared functionality instead of adding a local variant. Use SpotBugs (
mvn compile spotbugs:check), compiler warnings (mvn compile) and IDE inspections to find unused code. - Fix a transient environment problem (a stale PATH, a shell or editor that needs a restart) in the environment, by restarting or reconfiguring it; add no code that works around it.
- Push back when a request would violate an established principle (e.g. breaking test hermeticity). Explain the principle and suggest a documentation-only fix instead of silently implementing the harmful change.
- Update this handbook so the change is documented as well as implemented.
- Document only the latest state, integrated in the surrounding narrative (principles, behavior, rationale), including the choices made and why.
- This contract holds only general rules for handling a request; project-specific guidance goes in the chapter on that topic.
- Do not stop at making tests green; align the implementation with the specification or intended design, and document the semantic reason in this handbook.
- Never remove or change existing tests (code or fixtures) without explicit permission. A change to an existing fixture (expected output, input, or data) is validated by the maintainer before it is kept, also when a tool writes it: propose the change with its reason, and keep it only after approval.
- Update
CHANGELOG.mdfor every change, internal ones included (tests, CI, refactoring, removed code): keep## Unreleaseda short summary of what changed since the last release. A feature that is new since the last release is one Added line, which later fixes update instead of getting lines of their own. Each line covers one concern; changes of the same concern share a line (such as editorial changes, or updated dependency versions). A line states what is true now, without the old behavior; a fix that only removes a divergence that should not have existed (one part behaving unlike the rest) gets a few words in the line of its concern at most. - Before a release, propose a review of everything changed since the previous release: the code for correctness, and the documentation and changelog for accuracy and brevity.
- Check whether
README.mdneeds updates for user-visible behavior or workflow changes, and update it when needed. - Write documentation (this handbook, READMEs,
TODO.md,CHANGELOG.md, code comments) as plain positive statements: say what is true and leave out the contrast ("X, not Y"). Keep a negative only when it is the point itself, such as a prohibition, a warning, or a known limitation. - If there are difficulties during fulfillment, document them in the most appropriate existing handbook location (create a new chapter only when truly necessary) so future requests start with better context.
- A preference or principle that the maintainer states while handling a request is documented so that every later request follows it: a general one in this contract (and in the software-handbook skill it comes from), a project-specific one in the handbook chapter it belongs to. When it is unclear which, ask.
- When a request is a list of feedback (such as a
TODO.md), clean up after handling it: remove the items that are done, keep every open item as a clear task (an open question or an offered follow-up is an open item), and remove temporary files created along the way.
All packages live under be.ugent.idlab.knows.functions.agent.
- Entry points (package root):
Agent: the public interface.execute(functionId, arguments),execute(functionId, arguments, debug)andgetFunctions(). AnAgentisAutoCloseableand closes loaded function libraries.AgentFactory:createFromFnO(String... pathToFnoDocs)and an overload taking a map of implementation locations. Paths may be local files, URLs, classpath resources or an FnO document as a string.AgentImpl: the implementation; it also offerswriteModel(path)andexecuteToFile(...)to serialize the loaded model or an execution as RDF.Arguments: the parameter-IRI-to-value(s) container passed toexecute.DescriptionGenerator: builds RDF descriptions from the internal model.
functionModelProvider:FunctionModelProvideris the extension point for function description formats.fno.FnOFunctionModelProviderreads FnO documents with Apache Jena;fno.Namespacesholds the vocabulary IRIs (LIBis the deprecatedlib:vocabulary for implementations, still read with a warning);fno.exceptionhas one exception per missing or malformed part of a description, all subclasses ofFnOException, thrown while loading descriptions.model: the format-independent function model (Function,Parameter,FunctionMapping,MethodMapping,Implementation,FunctionCompositionand the composition mapping classes).model.fno.FnOParameteradds the resource IRI and type IRI that FnO parameters carry.functionInstantiation:Instantiatorresolves aFunctionto a callableThrowableFunction, via Java reflection for implementations and viagetCompositeMethodfor compositions. Its exceptions, infunctionInstantiation.exception, are subclasses ofFunctionInstantiationExceptionand are thrown while executing;FunctionNotFoundExceptionamong them is whatAgent.executethrows for an unknown function id. The composition algorithm (safety checks, cycle detection, execution stack, lambda construction, caching) is described step by step inREADME.mdunder "Function Composition - how it currently works".dataType:DataTypeConverterimplementations convert argument values to the Java types the implementation expects;DataTypeConverterProviderselects one per type.exception: general agent exceptions.util:FileFinderresolves a path as a remote URL, then as a file relative to the working directory, then as a classpath resource.
Runtime dependencies are jena-arq, jena-core, commons-collections4 and slf4j-api. jena-core shares the jena.version property with jena-arq.
- Build:
mvn compile;mvn packagebuilds the library jar. - Test:
mvn test. CI (.gitlab-ci.yml) runsmvn $MAVEN_CLI_OPTS testonmaven:3-eclipse-temurin-21-alpinefor every branch exceptmainanddevelopment, using.m2/settings.xml. - CI also includes the shared
rml/util/ci-templatesCHANGELOG.gitlab-ci.ymlcheck (thelintstage), which requiresCHANGELOG.mdto be updated, andMaven-Central.gitlab-ci.ymlfor deployment. - Linter: SpotBugs 4.10.3 (
spotbugs-maven-plugin4.10.3.0, configured in<pluginManagement>as in MappingWeaver-java and not bound to a phase). Runmvn compile spotbugs:check. Known state:spotbugs:checkreports 24 findings (mostly EI_EXPOSE_REP and EI_EXPOSE_REP2 in the model classes) and fails the build, so it runs on demand and CI does not run it. No formatter is configured.
Test classes follow the main packages; the test package for functionInstantiation is functionInstantiator. They are AgentTest (end-to-end execution, compositions, partial application, overloads, writing models), ArgumentsTest, GeneratorTest, dataType/DataTypeConverterTest, functionInstantiator/InstantiatorTest, functionModelProvider/fno/FnOFunctionProviderTest, and util/FileFinderTest and util/JarFileTest. internalfunctions/InternalTestFunctions holds the Java methods that test FnO documents map to.
Some tests write files into the working directory (the repository root when run with Maven): test.txt and test0.txt are produced by print side effects in sum-composition.ttl and complex_side_path.ttl, test1.txt by AgentTest.functionWithoutReturnValue, and testFileWrite.ttl and testExecution.ttl by AgentTest.testWriteModel and testWriteExecutionToFile. .gitignore excludes them (test*.txt, test*.ttl).
src/test/resources/ is flat. It contains:
- FnO documents (
*.ttl), one per scenario: basic functions (internalTestFunctions.ttl,generalFunctions.ttl,identityInteger.ttl), compositions (sum-composition.ttl,squareOfSum.ttl,computation.ttl,complex_side_path.ttl,weirdComposition*.ttl,cyclic.ttl), partial application (add10*.ttl,partialApplicationNoMappings.ttl,badPartialApplication*.ttl), invalid descriptions (badFunction.ttl,badParameter.ttl), RDF sequences (rdfSeq*.ttl), aliases and optional-parameter overloads. - External implementation JARs,
GrelFunctions.jarandAaabimFunctions.jar, with the FnO descriptionaaabim_java_mapping.ttl. Thegrel-functions-javatest dependency (via JitPack, version in thegrel.java.versionproperty) shipsfunctions_grel.ttl(the GREL function descriptions) andgrel_java_mapping.ttlat its jar root. Tests load both from the classpath, so the repository keeps no copy and a new grel release updates the descriptions with a version bump. simplelogger.propertiesfor test logging.
Step-by-step instructions are in RELEASE.md.
bump-version.sh tags a release v<version>; a testrelease-* name is used as-is for the tag and gets no next -SNAPSHOT. The release Maven profile builds source and Javadoc jars, signs them with GPG, and publishes to Maven Central through central-publishing-maven-plugin; the shared CI template runs that deployment.