Toolversiebeheer en compatibiliteit
Semantische versie-indeling voor tools, achterwaartse compatibiliteit en patronen voor uitfasering.
Toolversiebeheer en compatibiliteit is een gratis AI-agenten-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject AI-agenten. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus AI-agenten bevat in totaal 4 lessen.
Waarom versiebeheer voor hulpmiddelen belangrijk is
Wanneer de interface van een hulpmiddel verandert — een parameter wordt hernoemd, een verplicht veld wordt toegevoegd of de structuur van een retourwaarde verandert — werken agents die afhankelijk zijn van de oude interface ongemerkt niet meer. Versiebeheer met semantische regels en meldingen over veroudering voorkomt dit.
Semantische versienummering voor hulpmiddelen
Gebruik semantische versienummering: MAJOR.MINOR.PATCH. Verhoog MAJOR bij wijzigingen die bestaande gebruikers breken (verwijderde parameters, gewijzigde parametertypen of gewijzigde retourstructuur), MINOR bij achterwaarts compatibele toevoegingen en PATCH bij foutoplossingen die de interface niet beïnvloeden.
VERSIONING_RULES = {
'major_bump': [
'Removed a required or optional parameter',
'Renamed an existing parameter',
'Changed parameter type (e.g., string -> object)',
'Changed response field names or types',
'Removed a response field',
'Changed error code values'
],
'minor_bump': [
'Added an optional parameter',
'Added a new response field',
'Added a new tool to the plugin'
],
'patch_bump': [
'Fixed a bug without interface change',
'Improved error messages',
'Performance improvement',
'Updated documentation'
]
}
for bump_type, examples in VERSIONING_RULES.items():
print(f'{bump_type}:')
for ex in examples[:2]:
print(f' - {ex}')Versies parseren en vergelijken
Implementeer hulpprogramma's voor het vergelijken van versies om de compatibiliteit te controleren. Een agent kan in de configuratie de minimaal vereiste versie van een hulpmiddel opgeven en het register weigert hulpmiddelen die niet aan deze vereiste voldoen.
from functools import total_ordering
@total_ordering
class Version:
def __init__(self, version_str: str):
parts = version_str.strip().split('.')
if len(parts) != 3 or not all(p.isdigit() for p in parts):
raise ValueError(f'Invalid version: {version_str}')
self.major, self.minor, self.patch = map(int, parts)
def __str__(self):
return f'{self.major}.{self.minor}.{self.patch}'
def __eq__(self, other):
return (self.major, self.minor, self.patch) == (other.major, other.minor, other.patch)
def __lt__(self, other):
return (self.major, self.minor, self.patch) < (other.major, other.minor, other.patch)
def is_compatible_with(self, required: 'Version') -> bool:
"""Compatible if same major version and >= required minor.patch"""
return self.major == required.major and self >= required
v = Version('2.3.1')
required = Version('2.1.0')
print(f'{v} compatible with {required}: {v.is_compatible_with(required)}')
print(f'Is newer: {v > required}')Versies vastzetten in de agentconfiguratie
Agentconfiguraties moeten voor elke afhankelijkheid van een hulpmiddel de minimaal vereiste versie vastzetten. Zo voorkom je dat een agent per ongeluk een incompatibele nieuwere versie van een hulpmiddel gebruikt wanneer de plug-in wordt bijgewerkt.
AGENT_TOOL_REQUIREMENTS = {
'get_weather': '>=1.2.0',
'search_knowledge_base': '>=3.0.0',
'send_email': '>=2.1.0,<3.0.0' # exclude major-version bump
}
def parse_version_constraint(constraint: str) -> list:
"""
Parses constraints like '>=1.2.0,<3.0.0'
Returns list of (operator, Version) tuples
"""
ops = {'>=': lambda a, b: a >= b, '>': lambda a, b: a > b,
'<=': lambda a, b: a <= b, '<': lambda a, b: a < b,
'==': lambda a, b: a == b}
parts = [p.strip() for p in constraint.split(',')]
parsed = []
for part in parts:
for op_str, op_fn in ops.items():
if part.startswith(op_str):
parsed.append((op_fn, Version(part[len(op_str):])))
break
return parsed
def satisfies_constraint(tool_version: str, constraint: str) -> bool:
v = Version(tool_version)
rules = parse_version_constraint(constraint)
return all(op(v, required) for op, required in rules)
print(satisfies_constraint('2.3.0', '>=2.1.0,<3.0.0')) # True
print(satisfies_constraint('3.0.0', '>=2.1.0,<3.0.0')) # FalseWaarschuwingen voor veroudering
Wanneer je een parameter verwijdert of hernoemt, markeer deze dan eerst als verouderd in een MINOR-versie: laat de parameter werken, maar geef een waarschuwing voor veroudering terug in het antwoord. Verwijder de parameter pas in de volgende MAJOR-versie. Zo krijgen ontwikkelaars van agents tijd om hun code bij te werken.
import warnings
def execute_get_weather(params: dict) -> dict:
# Handle deprecated parameter 'temp_unit' -> replaced by 'units'
if 'temp_unit' in params:
warnings.warn(
'Parameter temp_unit is deprecated since v1.3.0. '
'Use units instead. Will be removed in v2.0.0.',
DeprecationWarning,
stacklevel=2
)
params = dict(params)
params['units'] = params.pop('temp_unit')
# Include deprecation notice in response
result = _fetch_weather(params['city'], params.get('units', 'celsius'))
if 'temp_unit' in params:
result['_deprecation_warnings'] = [
'temp_unit deprecated; use units'
]
return result
# When calling deprecated param:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
# result = execute_get_weather({'city': 'London', 'temp_unit': 'celsius'})
print('Deprecation warnings would be captured here')Migratiehandleidingen
Publiceer voor elke verhoging van de MAJOR-versie een migratiehandleiding waarin precies staat wat er is gewijzigd en waarin codevoorbeelden van vóór en na de wijziging staan. Zonder migratiehandleiding kunnen ontwikkelaars niet veilig upgraden.
MIGRATION_GUIDES = {
'1.x_to_2.0': {
'summary': 'Response structure changed: temperature is now nested under data{}',
'breaking_changes': [
{
'description': 'temperature field moved',
'before': 'result["temperature"]',
'after': 'result["data"]["temperature"]'
},
{
'description': 'temp_unit parameter removed',
'before': 'execute({"city": "London", "temp_unit": "celsius"})',
'after': 'execute({"city": "London", "units": "celsius"})'
}
],
'migration_steps': [
'1. Update parameter name: temp_unit -> units',
'2. Update response access: result["temperature"] -> result["data"]["temperature"]',
'3. Run your test suite against v2.0.0'
]
}
}
for guide_key, guide in MIGRATION_GUIDES.items():
print(f'Migration guide {guide_key}:')
print(f' {guide["summary"]}')
print(f' Steps: {len(guide["migration_steps"])}')Compatibiliteitsmatrix
Een compatibiliteitsmatrix legt vast welke versies van het hulpmiddel compatibel zijn met welke versies van je agentframework. Publiceer en onderhoud deze als onderdeel van de documentatie van je plug-in.
COMPATIBILITY_MATRIX = {
'weather-tools': {
'1.x': {'framework_min': '0.8.0', 'framework_max': '0.x.x', 'status': 'EOL'},
'2.x': {'framework_min': '1.0.0', 'framework_max': '1.x.x', 'status': 'supported'},
'3.x': {'framework_min': '2.0.0', 'framework_max': None, 'status': 'latest'}
}
}
def check_compatibility(
plugin_name: str,
tool_version: str,
framework_version: str
) -> dict:
matrix = COMPATIBILITY_MATRIX.get(plugin_name, {})
major = tool_version.split('.')[0] + '.x'
row = matrix.get(major)
if not row:
return {'compatible': False, 'reason': 'Version not in matrix'}
fw = Version(framework_version)
min_fw = Version(row['framework_min'])
compatible = fw >= min_fw
return {'compatible': compatible, 'status': row['status'],
'min_framework': row['framework_min']}
result = check_compatibility('weather-tools', '2.3.0', '1.2.0')
print(result)Versieregister
Het register voor hulpmiddelen moet versiegegevens opslaan voor elk geladen hulpmiddel en waarschuwen wanneer twee plug-ins dezelfde naam voor een hulpmiddel met verschillende versies aanbieden. Geef de voorkeur aan nieuwere versies, tenzij een beperking iets anders voorschrijft.
class VersionedToolRegistry(ToolRegistry):
def register_tool(self, name, schema, execute_fn, plugin_name):
if name in self._tools:
existing_v = Version(self._tools[name]['schema'].get('version', '0.0.0'))
new_v = Version(schema.get('version', '0.0.0'))
if new_v > existing_v:
print(f'Upgrading tool {name}: {existing_v} -> {new_v}')
else:
print(f'Keeping tool {name} v{existing_v} '
f'(skipping older v{new_v} from {plugin_name})')
return
super().register_tool(name, schema, execute_fn, plugin_name)
def get_version(self, tool_name: str) -> str:
tool = self._tools.get(tool_name)
if not tool:
return None
return tool['schema'].get('version', 'unknown')
def check_requirement(self, tool_name: str, constraint: str) -> bool:
v = self.get_version(tool_name)
if not v:
return False
return satisfies_constraint(v, constraint)Versieverschillen netjes afhandelen
Wanneer een agent wordt geladen en een vereist hulpmiddel niet aan de versiebeperking voldoet, mag je dit niet stilzwijgend negeren. Mogelijkheden zijn: meteen stoppen (het veiligst), in beperkte modus werken (zonder het hulpmiddel) of waarschuwen en doorgaan.
class VersionCheckResult:
def __init__(self):
self.satisfied = []
self.unsatisfied = []
self.missing = []
def check_all_requirements(
requirements: dict,
registry
) -> VersionCheckResult:
result = VersionCheckResult()
for tool_name, constraint in requirements.items():
installed_v = registry.get_version(tool_name)
if installed_v is None:
result.missing.append(tool_name)
elif not satisfies_constraint(installed_v, constraint):
result.unsatisfied.append({
'tool': tool_name,
'required': constraint,
'installed': installed_v
})
else:
result.satisfied.append(tool_name)
return result
def start_agent_with_version_check(requirements, registry):
check = check_all_requirements(requirements, registry)
if check.missing:
raise RuntimeError(f'Missing tools: {check.missing}')
if check.unsatisfied:
for item in check.unsatisfied:
print(f'VERSION MISMATCH: {item["tool"]} '
f'requires {item["required"]}, got {item["installed"]}')
raise RuntimeError('Tool version requirements not satisfied')
print('All tool requirements satisfied')Automatisering van wijzigingslogboeken
Genereer automatisch een wijzigingslogboek uit je git-commitberichten met behulp van het conventionele commitformaat. Zo blijven je migratiehandleidingen en release-opmerkingen altijd actueel.
# Conventional commit format:
# feat!: (major) remove temp_unit parameter
# feat: (minor) add 'humidity_pct' to response
# fix: (patch) handle API timeout correctly
# docs: update README
import subprocess
def generate_changelog_from_git(
from_tag: str = 'v1.2.0',
to_tag: str = 'HEAD'
) -> dict:
try:
log = subprocess.check_output(
['git', 'log', f'{from_tag}..{to_tag}',
'--oneline', '--pretty=format:%s'],
text=True
).strip().split('\n')
except subprocess.CalledProcessError:
return {'error': 'git log failed'}
changelog = {'breaking': [], 'features': [], 'fixes': [], 'docs': []}
for msg in log:
if msg.startswith('feat!'):
changelog['breaking'].append(msg[5:].strip())
elif msg.startswith('feat:'):
changelog['features'].append(msg[5:].strip())
elif msg.startswith('fix:'):
changelog['fixes'].append(msg[4:].strip())
elif msg.startswith('docs:'):
changelog['docs'].append(msg[5:].strip())
return changelog
if __name__ == '__main__':
subprocess.check_output = lambda *a, **k: (
"feat!: remove temp_unit parameter\n"
"feat: add humidity_pct to response\n"
"fix: handle API timeout correctly\n"
"docs: update README"
)
changelog = generate_changelog_from_git()
print('Changelog:')
for section, items in changelog.items():
print(f' {section}: {items}')
Vergrendelingsbestanden voor reproduceerbaarheid
Houd, net als package-lock.json in npm, een vergrendelingsbestand voor hulpmiddelen bij waarin de exacte versie van elke geïnstalleerde plug-in staat. Controleer bij het starten van de agent of de geïnstalleerde versies overeenkomen met het vergrendelingsbestand. Zo zorg je voor reproduceerbare en voorspelbare implementaties in verschillende omgevingen.
import json
import os
LOCK_FILE = '.tool-lock.json'
def generate_lock_file(registry) -> dict:
lock = {
'generated_at': __import__('datetime').datetime.utcnow().isoformat(),
'tools': {}
}
for tool_name, tool_info in registry._tools.items():
lock['tools'][tool_name] = {
'version': tool_info['schema'].get('version', 'unknown'),
'plugin': tool_info['plugin']
}
with open(LOCK_FILE, 'w') as f:
json.dump(lock, f, indent=2)
print(f'Lock file written: {len(lock["tools"])} tools')
return lock
def verify_lock_file(registry) -> bool:
if not os.path.exists(LOCK_FILE):
print('No lock file found — run generate_lock_file() first')
return False
with open(LOCK_FILE) as f:
lock = json.load(f)
for tool_name, locked_info in lock['tools'].items():
installed_v = registry.get_version(tool_name)
if installed_v != locked_info['version']:
print(f'VERSION MISMATCH: {tool_name} locked={locked_info["version"]} installed={installed_v}')
return False
print('Lock file verified: all versions match')
return True
if __name__ == '__main__':
import tempfile
os.chdir(tempfile.gettempdir())
class MockRegistry:
def __init__(self):
self._tools = {'get_weather': {'schema': {'version': '1.2.0'}, 'plugin': 'weather-tools'}}
def get_version(self, name):
return self._tools[name]['schema']['version']
registry = MockRegistry()
generate_lock_file(registry)
verify_lock_file(registry)
Kennistoets
Je voegt een optionele parameter format toe aan een bestaand hulpmiddel. Bestaande aanroepers gebruiken deze parameter niet. Welk versieonderdeel moet je verhogen?
Samenvatting: versiebeheer en compatibiliteit van hulpmiddelen
De belangrijkste punten uit deze les:
- Semantisch versiebeheer: MAJOR=brekende wijziging, MINOR=toevoeging, PATCH=oplossing
- Uitfasering: waarschuwen in MINOR, verwijderen in MAJOR; neem de uitfasering op in het antwoord
- Migratiehandleidingen: voor- en na-codevoorbeelden voor elke verhoging van MAJOR
- Compatibiliteitsmatrix: welke versies van hulpmiddelen werken met welke versies van het raamwerk
- Versies vastzetten: de configuratie van de agent specificeert beperkingen zoals
>=1.2.0,<2.0.0 - Direct falen: weiger het laden van hulpmiddelen die niet aan de beperkingen voldoen
Hierna: een marktplaats voor agent-plug-ins bouwen met publiceren, zoeken en installeren.
Leer AI-agenten met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 60
- Lessen
- 239
Veelgestelde vragen
Is de les “Toolversiebeheer en compatibiliteit” gratis?
Ja — de volledige tekst van “Toolversiebeheer en compatibiliteit” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus AI-agenten wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus AI-agenten bevat in totaal 4 lessen.
Wat leer ik in “Toolversiebeheer en compatibiliteit”?
Semantische versie-indeling voor tools, achterwaartse compatibiliteit en patronen voor uitfasering. Je oefent met AI-agenten door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met AI-agenten te beginnen?
Ervaring vooraf is niet nodig. AI-agenten op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “Toolversiebeheer en compatibiliteit”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over AI-agenten?
Ja. Elke les over AI-agenten bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Deelbare agenttools ontwerpen
- Plugins ontdekken en registreren
- Toolversiebeheer en compatibiliteit
- Een marketplace voor agentplugins bouwen